简体   繁体   English

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

[英]Best way to pass variables into callback functions in Node.js

I've been wondering, is there a better way to pass variables into callback functions in node.js other than using bind() . 我一直在想,有没有更好的方法将变量传递给node.js中的回调函数,而不是使用bind()

Here is an example: 这是一个例子:

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

Notice the bind() methods all the way up, simply passing the value of i . 注意bind()方法一直向上,只需传递i的值。

Thanks. 谢谢。

Variables in JavaScript are valid for the whole function scope . JavaScript中的变量对整个函数范围有效。 This means that you can define a variable x (( var x = ... ) and it is still accessible in all functions, you define within the same calling scope. (For detailed information you might want to take a look at JavaScript Closures 这意味着您可以定义一个变量x (( var x = ... ),并且它仍可在所有函数中访问,您可以在同一个调用范围内定义。(有关详细信息,您可能需要查看JavaScript闭包

The problem of your case is, that you manipulate your i during the for loop . 你的情况的问题是,你在for loop期间操纵你的i If simply access the i in the callback functions, you'd recieve the first value that is no longer in the loop . 如果只是在回调函数中访问i ,你就会收到循环中不再存在的第一个值。

You can avoid that by calling a new function with the i as argument, like this: 您可以通过使用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 would like to do with below: 我想在下面做:

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

You can use let instead of var in your for loop. 您可以在for循环中使用let而不是var。 This is (in my eyes at least) the biggest difference between the two! 这是(至少在我眼里)两者之间最大的区别! Just make sure you use strict mode or let won't work for you. 只要确保你使用严格模式或让我们不适合你。

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

The way I usually do it is to use .bind({vars here}) and then reference it with this.varname inside of the callback. 我通常这样做的方法是使用.bind({vars here}) ,然后在回调中使用this.varname引用它。 Make sure not to use arrow function on your callback, just a plain function. 确保不要在回调上使用箭头功能,只需使用普通功能。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM