Js:链接以清晰易读的方式承诺链接

时间:2018-10-11 08:21:57

标签: javascript node.js mongodb asynchronous

您好,有溢水口

我目前正在使用带有mongo数据存储的节点服务器来开发我的项目。我目前正在编写一些函数来为我填充数据库。
数据库中对象的示例包括“用户”,“班级”,“学年”,“学生评分”等。
创建此类对象的所有功能都是这样实现的:

    function popUser(users){
        chain = [];
        users.forEach((v,i,a)=>{
            let p = new Promise(function(res,rej){
                let newU = new User(v);
                newU.save(()=>{
                    err && rej(err);
                    res();
                });
            });
            chain.push(p);
        });
        return chain
    }

在我的填充模块的其余部分中,我会根据需要调用此类函数。调用上述函数的顺序很重要,因此我不希望完全并行执行构造函数。

有了Promises,我可以做这样的事情:

popUser(users).then(popClasses).then(...). ... .catch((err)=>{})

有了Promises Chains,我知道我可以做到以下

Promise.all(usersChain).then(()=>{
    //make a new chain for Classes
    Promise.all(classesChain).then (()=>{},(err)=>{})
},(err)=>{})

我认为我们可以同意,它变得很难阅读和理解,因此这个问题:

是否有一种方法可以使用更易读的不同语法来实现相同的结果?

编辑:更清楚地说,usersChain和cleassesChains是Promises数组,用于创建一些对象(一个或多个)并将其插入数据库。 我无法创建单个链,因为某些对象可能已经插入,而某些对象可能必须插入。

编辑:等等,我可以打电话给

Promsie.all(populateCountersPromise).then(promise1).then(promise2).catch((err)=>{})

3 个答案:

答案 0 :(得分:0)

代码中有不同的部分无法正常工作,或者不应以这种方式编写。

如果您使用这样的快捷方式:

err && rej(err);
res();

您应该知道它们的意思,因为它等于:

if( err ) { 
  rej(err);
}
res();

因此,如果发生错误,将同时调用rejres

从您的popUser返回一个Promises数组,所以popUser(users).then(popClasses)会失败,因为您无法在该数组上调用.then

您应该做的第一件事就是清理popUser函数:

function popUser(users) {

  let promises = users.map((v, i, a) => {
    return new Promise(function(res, rej) {
      let newU = new User(v);
      newU.save(err => {
        if (err) {
          rej(err)
        } else {
          res()
        }
      });
    });
  });

  return Promies.all(promises)
}

使用.map代替forEachpush,因为它使您从一开始就很清楚。并使用Promies.all从函数中返回一个Promise,等待所有用户被保存,如果对popClasses做同样的操作,则可以这样写:

popUser(users)
   .then(popClasses)
   .then(...)
   .catch((err)=>{})

如果您真的想像上一个代码片段一样编写它,则将其更改为:

Promise.all(usersChain)
  .then(() => Promise.all(classesChain))
  .then(() => {})
  .catch(err => {})

当今,许多API都支持经典回调和Promises,因此您可以进一步改善popUser

function popUser(users) {
  let promises = users.map(v => new User(v).save())
  return Promies.all(promises)
}

答案 1 :(得分:0)

猫鼬回调是旧版API。猫鼬支持承诺很长一段时间,不需要被承诺。

对于并发承诺,forEach可以替换为map,这是后者的确切用例:

function popUser(users){
  return Promise.all(
    users.map(userData => new User(userData).save())
  );
}

async..await可以在其他应许应按顺序进行的情况下使用:

try {
  await popUser(users);
  await popClasses();
  ...
} catch (err) {
  ...
}

答案 2 :(得分:0)

为什么不在函数Promise.all(chain)中返回popUser

返回承诺最好与popUser的语义相匹配,这是异步执行的功能。返回promise数组会造成混淆。

然后您可以使用popUsers.then(popClasses).then(...). ... .catch((err)=>{})将诺言排队