Node.JS如何在当前范围之外设置一个variables

我有一些代码,我不能得到我的头,我试图返回一个对象数组使用callback,我有一个函数,返回的值,然后推他们到一个数组,但我不能访问这个function以外,我在这里做了一些愚蠢的事情,但不知道是什么(我对Node.JS非常陌生)

for (var index in res.response.result) { var marketArray = []; (function () { var market = res.response.result[index]; createOrUpdateMarket(market, eventObj , function (err, marketObj) { marketArray.push(marketObj) console.log('The Array is %s',marketArray.length) //Returns The Array is 1.2.3..etc }); console.log('The Array is %s',marketArray.length) // Returns The Array is 0 })(); } 

你有多个问题在这里进行。 一个核心问题是了解asynchronous响应如何工作以及何时执行哪些代码。 但是,除此之外,您还必须学习如何pipe理循环中的多个asynchronous响应,以及如何知道所有响应何时完成以及如何按顺序获取结果以及在node.js中最好使用哪些工具去做。

你的核心问题是时机问题。 createOrUpdateMarket()函数可能是asynchronous的。 这意味着它在调用该函数时开始操作,然后在将来某个时候调用它的callback函数。 同时其余的代码继续运行。 因此,在调用callback之前,您正在尝试访问数组。

因为不能准确知道callback被调用的时间,所以唯一可以可靠地使用callback数据的地方是在callback中,或者是在callback中调用的东西。

你可以在这里阅读更多关于asynchronous/callback问题的细节: 为什么我的variables在函数内部修改后没有改变? – asynchronous代码引用

要知道所有这些createOrUpdateMarket()操作的全部完成时间,您必须特别编写代码,以了解何时完成了所有这些操作,并且不能依赖简单的for循环。 现代的方法是使用承诺,这些承诺提供工具来帮助您pipe理一个或多个asynchronous操作的时间。

另外,如果你想从for循环中累积结果,你必须在for循环之前声明并初始化它,而不是在for循环中。 这里有几个解决scheme:

手动编码的解决scheme

 var len = res.response.result.length; var marketArray = new Array(len), cntr = 0; for (var index = 0, index < len; index++) { (function(i) { createOrUpdateMarket(res.response.result[i], eventObj , function (err, marketObj) { ++cntr; if (err) { // need error handling here } marketArray[i] = marketObj; // if last response has just finished if (cntr === len) { // here the marketArray is fully populated and all responses are done // put your code to process the marketArray here } }); })(index); } 

标准承诺build成Node.js

 // make a version of createOrUpdateMarket that returns a promise function createOrUpdateMarketAsync(a, b) { return new Promise(function(resolve, reject) { createOrUpdateMarket(a, b, function(err, marketObj) { if (err) { reject(err); return; } resolve(marketObj); }); }); } var promises = []; for (var i = 0; i < res.response.result.length; i++) { promises.push(createorUpdateMarketAsync(res.response.result[i], eventObj)); } Promise.all(promises).then(function(marketArray) { // all results done here, results in marketArray }, function(err) { // an error occurred }); 

Bluebird Promise库增强了承诺

蓝鸟许诺库提供了Promise.map() ,它将遍历你的数据数组并产生一个asynchronous获得的结果数组。

 // make a version of createOrUpdateMarket that returns a promise var Promise = require('bluebird'); var createOrUpdateMarketAsync = Promise.promisify(createOrUpdateMarket); // iterate the res.response.result array and run an operation on each item Promise.map(res.response.result, function(item) { return createOrUpdateMarketAsync(item, eventObj); }).then(function(marketArray) { // all results done here, results in marketArray }, function(err) { // an error occurred }); 

asynchronous库

您也可以使用asynchronous库来帮助pipe理多个asynchronous操作。 在这种情况下,可以使用async.map()来创build一个结果数组。

 var async = require('async'); async.map(res.response.result, function(item, done) { createOrUpdateMarker(item, eventObj, function(err, marketObj) { if (err) { done(err); } else { done(marketObj); } }); }, function(err, results) { if (err) { // an error occurred } else { // results array contains all the async results } });