ES6 很可能会出现简单的 promise 错误

Posted

技术标签:

【中文标题】ES6 很可能会出现简单的 promise 错误【英文标题】:Likely, easy promises error with ES6 【发布时间】:2016-04-22 18:55:45 【问题描述】:

我对这段代码要发疯了。我已经尝试了所有我能想到的方法,我知道这与承诺有关……但我无法让它发挥作用!

原始代码不像我分享的那么简单,但这是问题的核心:

让我们有两个填充数组和两个空数组。 然后,“crearMazo”必须运行其中一个填充数组的循环,在我的 mongodb (mongoose) 上搜索这些字符串,并将生成的 _id 推送到其中一个空数组中。

好吧,它不起作用。 最后一个 console.log 显示一个空数组,即使循环内的 console.log 确实打印了数组。

我知道...我做错了承诺(显然)...但我找不到 :(

var cartas = ['Lorem', 'Lorem2', 'Lorem3', 'Lorem4', 'Lorem5', 'Lorem6', 'Lorem7', 'Lorem8'];
var cartas2 = ['Lorem', '2Lorem', '3Lorem', '4Lorem', '5Lorem', '6Lorem', '7Lorem', '8Lorem'];
var newMazo = [];
var newMazo2 = [];


let crearMazo = function (c,m) 
  return new Promise((resolve, reject) => 
    setTimeout(() => 
      for(var i in c)
        Card.findOne('nombre': c[i], '_id').then( carta => 
          m.push(carta._id);
        );
      
      resolve(m);
    , 0);
  );
;

crearMazo(cartas,newMazo)
  .then(crearMazo(cartas2,newMazo2))
  .then(() => 
     console.log('mazo: '+ newMazo);
     console.log('mazo: '+ newMazo2);
);

【问题讨论】:

我猜第二个console.log() 应该打印newMazo2 而不是newMazo,对吧? 【参考方案1】:

您必须将回调作为参数传递给then,而不是承诺。你可以使用

crearMazo(cartas,newMazo)
.then(() => crearMazo(cartas2,newMazo2))
.then(() => 
    console.log('mazo: '+ newMazo);
    console.log('mazo: '+ newMazo);
);

但正确的解决方案是并行运行它们,并使用它们各自的结果:

Promise.all([
  crearMazo(cartas, []),
  crearMazo(cartas2, [])
]).then(([newMazo, newMazo2]) => 
    console.log('mazo1: '+ newMazo);
    console.log('mazo2: '+ newMazo2);
);

您还在这里循环启动异步操作,并为它们创建多个承诺 - 无需等待其中任何一个。你会想要

function crearMazo(c, m) 
  return new Promise((resolve) => setTimeout(resolve, 0)) // is that actually needed?
  .then(() => 
    var promises = c.map(n =>
      Card.findOne('nombre': n, '_id').then(carta => carta._id);
    );
    return Promise.all(promises);
//         ^^^^^^^^^^^
  ).then(res =>
    m.concat(res)
  );

【讨论】:

感谢您的快速回答,@bergi :) 在应用正确的解决方案后我仍然遇到同样的问题 :( 我认为问题在于 mongoose 查询没有“发回”数组(我什至不知道如何“说”它,抱歉)。如果我在“m.push(carta._id); 之后添加一个“console.log('mazo query: '+ m);" ",我在循环结束时在 console.log 上得到了正确的数组。但是 mazo1 和 mazo2 仍然是空的。 哦,等等,我完全忽略了你在那里的循环中使用了 Promise。您必须在其中创建的所有 Promise 上使用 Promise.all 才能等待它们。 嘿!我们到了某个地方 :) : 现在我得到了最终的数组 "mazo1: ,,,,,,,"。 这可能意味着您正在接收的对象的_ids 是nullundefined 或空字符串。 事实上,在 carta._id 在 console.log 打印正确的 id 之前,它不是 :( "console.log(carta._id);"。但它仍然在 mazo1 和 mazo2 之后打印它们,顺便说一句。

以上是关于ES6 很可能会出现简单的 promise 错误的主要内容,如果未能解决你的问题,请参考以下文章

es6-----promise

es6

ES6 中Promise 使用

ES6:何为Promise?

ES6 Promise 用法

处理 Promise 中的错误 - Es6