【问题标题】:Second promise does not run (NodeJS)第二个承诺不运行(NodeJS)
【发布时间】:2019-08-06 21:30:26
【问题描述】:

我正在尝试学习 Nodejs 中的 Promise。碰巧当我尝试运行两个承诺时,第一个得到解决,但第二个既不拒绝也不解决。

更新 - 承诺没有按顺序运行。

两种方法都试过了

let promiseConnectMongo = mongoDB.connectMongo();
let promiseCreateCollections = mongoDB.createCollections();

第一:

promiseConnectMongo
.then((result) => {
    console.log(result);
    return promiseCreateCollections;
});

第二:

promiseConnectMongo.then((result) => {
    console.log(result);
    promiseCreateCollections.then((result) => {
        console.log(result);
    });

两种方法(不要太花哨):

connectMongo: function () {
    return new Promise((resolve, reject) => {
        MongoClient.connect(url, { useNewUrlParser: true }, (err, db) => {
            if (err)
                reject("Failed to connect db.\n")
            else {
                dbase = db.db(dbName);
                resolve("Connected sucessfully to the database: " + dbName);
            }
        });
    });

},

createCollections: function () {
    return new Promise((resolve, reject) => {

        console.log("Creating collections");

        dbase.createCollection("products", (err, result) => {
            if (err)
                reject(err);
            console.log(result);
        })
            .then(() => dbase.createCollection("bag", (err, result) => {
                if (err)
                    reject(err);
                console.log(result);
            }))
            .then(() => dbase.createCollection("brands", (err, result) => {
                if (err)
                    reject(err);
                console.log(result);
            }))

        resolve("Collections created sucessfully");
    });
}

输出是:

更新的输出 为什么第二个 Promise 先运行?

【问题讨论】:

  • createCollection 只有在没有通过回调的情况下才返回promise,所以可能会出现js错误。您可以通过删除该回调来进行检查吗?

标签: node.js mongodb asynchronous promise


【解决方案1】:

我认为其中一些将与您如何使用 Promise 有关。具体来说,我看到你遵循这种模式:

somethingAsync
  .then(Math.random())
  .then(x => console.log(x)) // undefined

您可能期望得到随机数,但实际情况是您将调用Math.random 的结果传递给.then 回调。您在几个地方遵循这种模式,例如:

.then(dbase.createCollection("bag", (err, result) => ...))

使用这样的方法意味着它不会等待您的createCollection 完成。它只是将undefined 传递到管道中。这意味着createCollections 几乎立即解析为undefined 作为其值。

你可以简单地通过包装你的电话来解决这个问题:

.then(() => dbase.createCollection("bag", (err, result) => ...))
//    ^^^^^

【讨论】:

  • 好的,所以我按照你的说法进行了包装,并在 createCollection() 承诺的开头添加了一个打印(“创建集合”)。 (问题已更新)。但是,当我运行程序时会发生这种情况,输出首先显示相同的打印,然后显示“连接成功...”,即使它应该首先解析 connectPromise,然后是 createPromise,如代码所示。跨度>
【解决方案2】:

我可以在createCollection 中看到一些问题,如果您想在 mongo 中创建多个集合,可以这样做:

function createCollection (){
    return Promise.all([
        dbase.createCollection('products'),
        dbase.createCollection('bag'),
        dbase.createCollection('brands')
    ])
}

因此您无需创建自定义承诺并返回它。这将并行创建所有三个集合,并在所有三个集合完成后解决。

然后您可以在 then 函数中访问它们的响应,如下所示:

createCollection()
.then(resArray=>{
   console.log(resArray[0],resArray[1],resArray[2])
})

但请记住,如果任何一个集合创建失败,promise form createCollection 将会失败。

您也可以并行创建集合,但我不建议这样做,因为它们不相互依赖。

【讨论】:

  • 感谢您的回复!这种方式要容易得多!但是 dbase 是未定义的,因为它似乎也首先运行了这个 Promise,所以当它尝试创建一个集合时,会抛出一个 TypeError。
猜你喜欢
  • 2017-12-21
  • 1970-01-01
  • 1970-01-01
  • 2021-02-18
  • 2020-06-16
  • 2018-06-09
  • 2020-06-04
  • 2021-05-19
  • 2015-03-08
相关资源
最近更新 更多