外部变量不能在Promise内部改变.然后函数

Outer variables not being altered inside Promise.then function

本文关键字:改变 然后 函数 内部 Promise 变量 不能 外部      更新时间:2023-09-26

在使用think .js的节点上,我试图通过循环迭代并将每个项目添加到数组中。然而,由于某种原因,这并不奏效。

在另一个地方,它是相同的和工作,只是没有一个承诺。然后函数。为什么这不起作用?

var fixedItems = [];
for (i in tradeItems) {
  var item = tradeItems[i];
  Item.get(item["id"]).run().then(function(result) {
    var f = { "assetid": result["asset_id"] };
    console.log(f);  // WOrks
    fixedItems.push(f); // Doesn't work
  });
}
console.log(fixedItems); // Nothing

Promise表示任务的未来结果。在本例中,您在任务(对Item.get的调用)完成工作之前记录fixedItems。也就是说,then函数还没有运行,所以fixedItems中没有任何东西。

如果你想使用fixedItems一旦它包含了所有的项目,你需要等待所有的承诺解决。

你怎么做取决于你正在使用的承诺库。这个Promise.all的例子可以与许多库一起工作,包括原生ES6 Promises:

// Get an array of Promises, one per item to fetch.
// The Item.get calls start running in parallel immediately.
var promises = Object.keys(tradeItems).map(function(key) {
  var tradeItem = tradeItems[key];
  return Item.get(tradeItem.id);
});
// Wait for all of the promises to resolve. When they do,
//  work on all of the resolved values together.
Promise.all(promises)
  .then(function(results) {
    // At this point all of your promises have resolved.
    // results is an array of all of the resolved values.
    // Create your fixed items and return to make them available
    //  to future Promises in this chain
    return results.map(function(result) {
      return { assetid: result.asset_id }
    });
  })
  .then(function(fixedItems) {
    // In this example, all we want to do is log them
    console.log(fixedItems);
  });

推荐阅读:HTML5 rocks introduction to Promises.

您的问题是在循环中的任何承诺完成执行之前调用console.log(fixedItems)。一种更好的解决异步问题的方法是先将所有项目id放在一个数组中,然后在单个查询中检索所有项目,这在数据库端也更有效。

var itemIds = tradeItems.map(function(item) {
    return item.id;
});
var fixedItems = [];
//you would need to write your own getItemsById() function or put the code
//to get the items here
getItemsById(itemIds).then(function(items) {
    items.forEach(function(item) {
        var f = { "assetid": result["asset_id"] };
        fixedItems.push(f);
    });
    whenDone();
});
function whenDone() {
    //you should be able to access fixedItems here
}

我不容易找到如何查找多个记录的ID在一个单一的查询与思考,但我确实找到了这个页面,这可能会有所帮助:http://c2journal.com/2013/01/17/rethinkdb-filtering-for-multiple-ids/

虽然这将是我解决这个问题的首选方法,但仍然可以使用多个查询并使用承诺链等待它们全部被解决,然后再继续执行后续代码。如果你想走这条路,看看这个链接:http://promise-nuggets.github.io/articles/11-doing-things-in-parallel.html。(注:我个人没有使用过Bluebird,但我认为链接中的Bluebird示例可能已经过时了。map方法似乎是当前推荐的使用承诺完成此操作的方法:https://stackoverflow.com/a/28167340/560114.)

更新:对于后一个选项,您可以使用上面joews回答中的代码。