正确处理Node Promise中的异步Mongo操作 [英] Correct handling of async Mongo actions in Node Promise

查看:67
本文介绍了正确处理Node Promise中的异步Mongo操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个执行多个Mongo动作的函数,最后一个动作是在完成所有其他动作后关闭数据库.我对这个问题的处理非常有信心,但是我有一些外部评论引起了人们的关注,我想验证我的解决方案是否正确.

I have a function which performs multiple Mongo actions, and the last action is to close the database after all other actions have completed. I was fairly confident of my handling of the issue, but I have had some external comments raise concerns, and I wanted to verify if my solution is correct.

建议的解决方案:

function updateDatabase (name, token) {
  return new Promise((resolve, reject) => {
    MongoClient.connect(MONGODB_URL)
      .then( (database) => {
          return database.collection('testCollection').update({name}, {$pull: {tokens: {$in: [token]}}})
            .then( () => {
              database.collection('log').insert({
                name,
                token
              });
              return database;
            })
      })
      .then( (db) => {
        db.close(true);
        resolve(`Invalid token: ${token} has been removed from: ${name}`);
      })
      .catch( (err) => {
        reject(err);
      })
  });
}

我的原始解决方案:

function updateDatabase (name, token) {
  return new Promise((resolve, reject) => {
    MongoClient.connect(MONGODB_URL)
      .then( (database) => {
        return database;
      })
      .then( (db) => {
        database.collection('testCollection').update({name}, {$pull: {tokens: {$in: [token]}}})
        return database;
      })
      .then( () => {
        database.collection('log').insert({
          name,
          token
        });
        return database;
      })
      .then( (db) => {
        db.close(true);
        resolve(`Invalid token: ${token} has been removed from: ${name}`);
      })
      .catch( (err) => {
        reject(err);
      })
  });
}

我的原始解决方案是否可行?建议的解决方案是更好的方法吗?两者都可以在测试中工作,但是要针对生产级负载,因此我需要确保在其他操作完成之前,数据库不会关闭,我相信这是我在原始解决方案中已经完成的.

Is my original solution way off the mark or is the suggested solution a better approach? Both work in testing but against a production grade load, I need to make sure the db does not close until other actions are complete, which I believe I have accomplished in my original solution.

推荐答案

由于MongoDB驱动程序的所有异步操作已经返回了promise,因此您根本不应该使用new Promise,而是建立一个promise链:

Since all asynchronous operations of the MongoDB driver already return a promise, you shouldn't use new Promise at all, but set up a promise chain:

function updateDatabase(name, token) {
  let database;
  return MongoClient.connect(MONGODB_URL).then(db => {
    database = db;
    return database
      .collection("testCollection")
      .update({ name }, { $pull: { tokens: { $in: [token] } } });
  })
  .then(() => {
    return database.collection("log").insert({
      name,
      token
    });
  })
  .then(() => {
    database.close(true);
  })
  .catch(err => {
    database.close(true);
    throw err;
  });
}

我知道您想将database作为下一个then的参数传递,但是您会遇到一个问题,即它在catch处理程序中将不可用.一种解决方案是使用函数作用域变量,该变量将在打开连接后分配,就像上面的代码一样.

I understand that you want to pass database as an argument for the next then, but you'll run into the issue that it won't be available in the catch handler. One solution is to use a function-scoped variable that gets assigned after opening the connection, like the code above does.

如果您不喜欢,可以在.then处理程序内为MongoClient.connect创建一个新的Promise链:

If you don't like that, you can create a new promise chain inside the .then handler for MongoClient.connect:

function updateDatabase(name, token) {
  return MongoClient.connect(MONGODB_URL).then(database => {
    return database
      .collection("testCollection")
      .update({ name }, { $pull: { tokens: { $in: [token] } } })
      .then(() => {
        return database.collection("log").insert({
          name,
          token
        });
      })
      .then(() => {
        database.close(true);
      })
      .catch(err => {
        database.close(true);
        throw err;
      });
  });
}

这篇关于正确处理Node Promise中的异步Mongo操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆