在Node.js中将变量传递给回调函数的最佳方法

13

我一直在想,除了使用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的值而一路上升的。

谢谢。


如果我没错的话,您可以在回调函数中使用迭代(i)值而不需要任何赋值。 - San
我认为你是错的。如果你不使用bind()方法运行它,console.log语句会显示 [ undefined ] done... - Justin
4个回答

15

在JavaScript中,变量在整个函数作用域内有效。这意味着您可以定义一个变量xvar x = ...),并且在同一调用作用域内定义的所有函数中仍然可以访问它。 (有关详细信息,您可能希望查看JavaScript Closures

您的问题在于,在for循环期间操作了i。 如果只是在回调函数中访问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
}

你怎么能把 i 直接作为函数参数传递给 writeFile() 呢?它的原型是 (filename, callback) 对吧?另外,为什么 fs.stat() 也没有将 i 作为函数参数传递呢? - Justin
我没有检查你的代码,只是将其转换为使用传递的变量:D - Tharabas
2
不必要的匿名函数会使脚本变慢。 - emj365

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));
}

0

在你的for循环中,可以使用let代替var。这是两者之间最大的区别(至少在我看来)!只要确保使用严格模式,否则let将无法正常工作。

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...");
            });
        });
    });
}

0
通常我会使用.bind({这里是变量}),然后在回调函数内部使用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}))
})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接