外部变量不能在Promise内部改变.然后函数
Outer variables not being altered inside Promise.then function
在使用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回答中的代码。
- 让文本输入幻灯片显示输入时的新文本输入?然后向后滑动
- 动态地改变“”的URL;添加新项目”;链接使用javascript/jquery
- Javascript运行php文件,然后下载文件
- 如何将屏幕分辨率乘以 80%,然后在代码中使用
- "改变“;列表头,然后继续处理列表
- 悬停在元素上改变元素,然后在悬停中包含该元素
- 外部变量不能在Promise内部改变.然后函数
- 你如何链承诺,但改变类型从一个然后到另一个
- 设置Javascript类的对象,然后改变它以某种方式改变所有实例的对象
- 在缩略图上更改滑块图像.图像改变一秒钟,然后恢复
- 改变循环中元素的背景,然后改变悬停的颜色
- 我如何使文本改变其他图像,然后用户鼠标悬停文本
- JQuery元素点击函数IF(对于每个css_attribute = value)然后改变css值
- jQuery在悬停时改变图像,然后在单击时保持图像
- Asp:RadioButtonList SelectedIndex不改变时,设置javascript,然后按钮被禁用
- 放大网页,然后点击后退按钮改变前一页的背景大小
- 扫描数据到mvc web应用程序,然后改变焦点
- 重新加载页面一次,然后再重新加载,不改变内容
- 检查互联网连接,然后改变图像在网页中的JQuery/Javascript/Ajax
- 改变位置.然后按后退按钮- IE的行为不同于其他浏览器