嵌套的承诺在.then在第一个promise节点之前运行

时间:2018-01-27 18:02:46

标签: javascript node.js mongodb promise es6-promise

我在我的程序中遇到问题,我在承诺的.then中运行了一个承诺,但它在第一个承诺之前运行第二个承诺。这不是我想要的,因为它依赖于第一个工作承诺。这是我的代码(console.logs是随机的,但我当场想出的东西可以检查运行的时间)

new Promise((resolve, reject) => {
    for (i = 0; i < 10; i++) {

        var query = {
            class: result[`class${i}`]
        };
        dbo.collection("homeworks").find(query).toArray(function(err, result) {
            if (err) throw err;
            for (i = 0; i < result.length; i++) {
                current = current + 1;
                console.log(current)
                allhomework[current] = result[i];
                console.log(allhomework[current])
            }
            db.close();

        });
    }
    console.log("HOLA");
    resolve(allhomework);
})
.then((allhomework) => {
    console.log("HOLA MIS AMIGOS")
    new Promise((resolve, reject) => {
        console.log("v");
        for (i = 0; i < 10; i++) {
            console.log("uaefshiudvhofdh")
            console.log(allhomework[1]);
        }
        resolve();
    }).then(() => {
        response.render('index', {
            username: req.session.user,
            homeworks: allhomework
        });
    })

})
.catch(console.log)

1 个答案:

答案 0 :(得分:2)

嗯,解决此问题的最佳方法是使用数据库的promise接口,并使用Promise.all()跟踪循环中所有异步数据库操作的完成时间。但是,如果你想用你现有的循环手动编码它,你只需要在它们全部完成时保留一个计数器。

new Promise((resolve, reject) => {
    let cntr = 10;
    for (let i = 0; i < 10; i++) {

        var query = {
            class: result[`class${i}`]
        };
        dbo.collection("homeworks").find(query).toArray(function(err, result) {
            if (err) {
                db.close();
                return reject(err);
            }
            for (let i = 0; i < result.length; i++) {
                current = current + 1;
                console.log(current)
                allhomework[current] = result[i];
                console.log(allhomework[current])
            }
            --cntr;
            if (cntr === 0) {
               db.close();
               resolve(allHomework);
            }
        });
    }
    console.log("HOLA");
});

关于此代码的其他说明:

我也想知道为什么在你的外圈中间有db.close()。我认为这会引起问题。

我还在reject(err)支票上添加了if (err)

您的i变量存在循环冲突。为每一个添加let以使它们分开或将其中一个更改为另一个字母。

这是一个在数据库中使用promise接口的版本。我能够完全摆脱内循环,让承诺收集所有结果,以便我们。如果你没有通过回调,Monbodb的.toArray()会返回一个与查询结果一起解析的承诺。我们可以使用Promise.all()来按顺序收集所有结果,并告诉我们它们何时完成:

let promises = [];
for (let i = 0; i < 10; i++) {
    let query = {
        class: result[`class${i}`]
    };
    promises.push(dbo.collection("homeworks").find(query).toArray());
}
Promise.all(promises).then(allResults => {
    // flatten the results into all one array - promises will have kept them in proper order
    db.close();
    let results = [].concat(...allResults);
    // now do whatever you want with the final array of results
}).catch(err => {
    db.close();
    // handle error here
});