Динамически заполнить Promise.all () - PullRequest
0 голосов
/ 11 июня 2018

Я пытаюсь выяснить, почему этот бит кода не работает.Я перебираю дерево зависимостей (deepObject), и для каждого я хочу запустить функцию, которая возвращает обещание.Затем я хотел бы, чтобы следующий набор функций выполнялся после разрешения всех обещаний, но журналы консоли внутри обещания не выполняются. ES6 тоже круто, если у вас есть лучший подход, однако я также очень хотел бы знать, почему этот код не работает.

обновлен, чтобы добавить .catch (это не имело никакого эффекта)

for (let i = 0; i < keys.length; i++) {
    promisesArray.push(promiseFunction(deepObject[keys[i]]));
}
Promise.all(promisesArray).then(resolved => {
    console.log('dep promises resolved');
    console.log(`resolved: ${JSON.stringify(resolved)}`);
}).catch(err => console.error(new Error(err));

// promiseFunction is recursive
promiseFunction(obj) {
    return new Promise((resolve, reject) => {

        const keys = Object.keys(deepObj);
        for (let j = 0; j < keys.length; j++) {
            if (Object.keys(deepObj[keys[j]]).length) {
                // adding return statement to following line breaks it
                // that was already recommended, see threads
                promiseFunction(deepObj[keys[j]]);
            } else {
                const dep = new Package(keys[j]);
                console.log(`skan dep: ${keys[j]}`);
                dep.fetch().then(() => {
                    return anotherFunction();
                }).then(() => {
                    return Promise.all([
                        promise1(),
                        promise2(),
                        promise3(),
                    ]).then(resolved => {
                        if (resolved[0].propertyINeed) {
                            resolve(true);
                        }
                        resolve(false);
                    });
                }).catch(err => {
                    console.error(new Error(err));
                    process.exit(1);
                });
            }
        }
    });

Я знаю этот разговор - обсуждался здесь - здесь

Во второй ссылке выше принятый ответ предполагает:

Если вы асинхронно заполняете массив, вы должны получить обещание для этого массива и использовать .then (Promise.all.bind (Promise)).Если вы не знаете, когда прекратите добавлять обещания, это все равно невозможно, поскольку все они могут вообще никогда не быть разрешены.

Однако я не использую асинхронное заполнение массива.Это нужно мне?Чего мне здесь не хватает?

update

Так как у меня теперь ведется журнал ошибок как в .then(), так и в .catch(), кажется, что что-то идет не так, не связанное с тем, что происходит внутриоб этом.

Добавление оператора возврата до promiseFunction(deepObj[keys[j]]); прервало рекурсию.Я перешел от итерации по 173 объектам к 68. При добавлении улова никаких дополнительных результатов не регистрировалосьПриведенный выше код обновлен, чтобы разделить больше рекурсивного fn.Когда я запускаю его, кажется, что он выполняет все обещания, но я не могу этого знать.Меня больше всего беспокоит знание того, что 1. массив обещаний для promise.all содержит все необходимые объекты и 2. ловит момент, когда все эти обещания для всех объектов внутри рекурсивного объекта разрешены.

Кроме того, для записи, каждая из этих функций, которые возвращают обещания, обязательно должна быть асинхронной.Я повторил все это несколько раз, пытаясь упростить и удалить все ненужные обещания.Задача просто сложная.Существует ряд шагов, которые должны быть выполнены, они являются асинхронными и объединены в цепочку, потому что они должны быть разрешены в определенном порядке.

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Давайте посмотрим на ваш promiseFunction ...

for (let j = 0; j < keys.length; j++) {
    if (Object.keys(obj[keys[j]]).length) {
        //if you get in here, promiseFunction returns undefined, and it never gets resolved
        promiseFunction(obj[keys[j]]);
    } else {
        const dep = new Package(keys[j]);
        console.log(`skan dep: ${keys[j]}`);
        // and some more async hell that all resolves correctly
        //but even if it resolves correctly, you still have the if...
    }
}

Чтобы добиться цели, просто верните promiseFunction результат в выражении if:

for (let j = 0; j < keys.length; j++) {
    if (Object.keys(obj[keys[j]]).length) {
        //if you get in here, you're saying this promise will depend on how this second promiseFunction will resolve
        return promiseFunction(obj[keys[j]]);
    } else {
        //omitted for brevity...
        resolve('your value');
    }
}

Теперь, когда вы входите в оператор if, вы в основном говорите об обещании решить, основываясь на том, правильно ли решена эта секунда promiseFunction - вы делегируете разрешение другому обещанию.

Я никогда никого не слышалдайте ему это имя, но вы можете думать об этом как о рекурсии Promise:)

0 голосов
/ 11 июня 2018
if (Object.keys(obj[keys[j]]).length) {
    promiseFunction(obj[keys[j]]);
} else {
    // and some more async hell that all resolves correctly

Если Object.keys(obj[keys[j]]).length равно true, то вы никогда не позвоните resolve или reject, поэтому обещание никогда не разрешится.

(Обратите внимание, что вызов promiseFunctionрекурсивно создает новое обещание, которое никогда не помещается в Promise.all).

Поскольку некоторые из ваших обещаний не разрешаются, Promise.all тоже не будет.


Вам, вероятно, нужно что-то более похожее на:

var promises = [];
processObject(obj);
Promise.all(promises).then(etc etc);

function processObject(object) {
    for ( loop; over; object ) {
        if (condition) {
             processObject(object[something]);
        } else {
             promises.push(new Promise( (res, rej) => {
                 // so something async
             });
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...