我一直在想,除了使用bind()
之外,是否有更好的方法将变量传递给node.js中的回调函数。
以下是一个例子:
var fs = require('fs');
for(var i = 0; i < 100; i++) {
fs.writeFile(i + ".txt", i, function(error) {
fs.stat(this.i + ".txt", function() {
fs.rename(this.i + ".txt", this.i + ".new.txt", function() {
console.log("[" + this.i + "] Done...");
}.bind({ i: this.i }));
}.bind({ i: this.i }));
}.bind({ i: i }));
}
注意bind()
方法一直向上,只需传递i
的值。
感谢。
答案 0 :(得分:15)
JavaScript中的变量对整个功能范围有效。
这意味着您可以定义变量x
((var x = ...
)并且仍然可以在所有函数中访问它,您可以在同一个调用范围内定义它。
(有关详细信息,您可能需要查看JavaScript Closures
您的案例的问题是,您在i
期间操纵了for loop
。
如果只是访问回调函数中的i
,您就会收到不再在循环中的第一个值。
您可以通过调用i
作为参数的新函数来避免这种情况,如下所示:
var fs = require('fs');
// still use your for-loop for the initial index
// but rename i to index to avoid confusion
for (var index = 0; index < 100; index++) {
// now build a function for the scoping
(function(i) {
// inside this function the i will not be modified
// as it is passed as an argument
fs.writeFile(i + ".txt", i, function(error) {
fs.stat(i + ".txt", function() {
fs.rename(i + ".txt", i + ".new.txt", function() {
console.log("[" + i + "] Done...");
});
});
});
})(index) // call it with index, that will be i inside the function
}
答案 1 :(得分:7)
我想在下面做:
var fs = require('fs');
var getWriteFileCallback = function(index) {
return function(error) {
fs.stat(index + '.txt', function() {
fs.rename(index + '.txt', index + '.new.txt', function() {
console.log("[" + index + "] Done...");
});
});
};
}
for(var i = 0; i < 100; i++) {
fs.writeFile(i + ".txt", i, getWriteFileCallback(i));
}
答案 2 :(得分:0)
您可以在for循环中使用let而不是var。这是(至少在我眼里)两者之间最大的区别! 只要确保你使用严格模式或让我们不适合你。
var fs = require('fs');
for(let i = 0; i < 100; i++) {
fs.writeFile(i + ".txt", i, function(error) {
fs.stat(i + ".txt", function() {
fs.rename(i + ".txt", i + ".new.txt", function() {
console.log("[" + i + "] Done...");
});
});
});
}
答案 3 :(得分:0)
我通常这样做的方法是使用.bind({vars here})
,然后在回调中使用this.varname引用它。确保不要在回调上使用箭头功能,只需要一个简单的函数。
someArray = [{id:1}, {id:4}, {id:10}]
someArray.forEach(item=>{
// item.id will be correct here
someAsyncFunc({id:item.id}, function(err, data){
// we need to use this.tempItem.id here because it could be returned sometime in the future
console.log(`someAsyncFunc on item.id ${this.tempItem.id} returned`)
}.bind({tempItem:item}))
})