将数据传递给node.js回调——异步问题
Passing data into node.js callbacks - the asynchronous issue
以下面的代码为例,其中用一些值初始化对象data
,然后由一些时间密集型函数(如数据库访问)处理这些值。如果执行成功,则将成功的data
项的名称打印到控制台中。否则,打印失败通知:
data = {first: 'someinfo', second: 'somemoreinfo', third: 'evenmoreinfo'};
for (var item in data) {
timeIntensiveFunction(item, data[item], function(err) {
if (!err) {
console.log(item + ' processed successfully');
} else {
console.log(item + ' failed');
}
});
}
您希望控制台显示这个,假设函数对所有三个数据项都成功:
first processed successfully
second processed successfully
third processed successfully
相反,它将显示,假设第一次数据库访问时间比for
循环长:
third processed successfully
third processed successfully
third processed successfully
这是因为控制台日志记录是在回调中完成的,只有在for
循环完成之后才合理地调用,因为timeIntensiveFunction()
需要很长时间。当第一个回调被调用时,item
已经有了它的最后一个值third
。
如何将item的"当前"值传递给回调函数?
问题是因为它只调用最后一项的回调。
你可以用下面的函数绑定你的每一个项目。
var printStatus = function(item){
return function(err) {
if (!err) {
console.log(item + ' processed successfully');
} else {
console.log(item + ' failed');
}
}
}
for (var item in data) {
timeIntensiveFunction(item, data[item], printStatus(item));
}
这是javascript中闭包的一个常见问题。解决这个问题的一种方法是将函数调用包装在一个匿名函数中,并作用域为item
。像这样:
for (var item in data) {
(function(item){
timeIntensiveFunction(item, data[item], function(err) {
if (!err) {
console.log(item + ' processed successfully');
} else {
console.log(item + ' failed');
}
});
})(item);
}
如果你正在寻找一个可以更容易地处理异步任务的库,请查看caolan/async.
var async = require("async");
var data = [{id: "first"}, {id: "second"}, {id: "third"}];
function timeIntensiveFunction(item, done) {
// do something
console.log("time intensive task started:", item.id);
// err?
// if (err) return done(err);
done();
}
function processItem(item, done) {
timeIntensiveFunction(item, function(err) {
if (err) return done(err);
console.log("task complete:", item.id);
done();
});
}
async.map(data, processItem);
输出time intensive task started: first
task complete: first
time intensive task started: second
task complete: second
time intensive task started: third
task complete: third
对于希望了解如何在没有库的情况下完成此操作的用户,您可以查看此答案的修订历史。
相关文章:
- Meteor:异步回调问题
- Meteor:异步函数回调异常:onAfterAction
- 异步中的回调函数出现问题'张贴'
- JavaScript中的异步回调
- 如何将此异步回调转换为生成器
- 在Nodejs中堆叠异步回调事件的最佳方式
- 如何使用jQuery等待来自回调的异步调用
- 从异步回调中获取值
- jasmine 2-在jasmine指定的超时时间内未调用异步回调.DEFAULT_TIMEOUT_INTERVAL
- 将数据注入异步回调(使用 node.js)
- 由于异步回调,变量被覆盖
- 与 promise 一起使用时,异步瀑布不执行下一个回调方法
- 如何将状态对象/数据传递给(异步)ajax 回调
- 管理Meteor中的异步回调
- 如何通过一个回调异步排队和执行多个promise
- 如何等到异步回调完成后才能使用检索到的数据
- 如何在node.js中通过API回调异步递归
- 将数据传递给node.js回调——异步问题
- 从回调(异步方法)内部访问对象文字属性
- 使 JavaScript 函数与回调异步