繁体   English   中英

Node.JS如何在当前范围之外设置变量

[英]Node.JS How to set a variable outside the current scope

我有一些我无法理解的代码,我试图使用回调返回对象数组,我有一个函数返回值,然后将其压入数组,但我无法在函数外部访问它,我在这里做一些愚蠢的事情,但是却无法分辨(我对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

                    })();

                }

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

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

因为您无法确切知道何时将调用该回调,所以唯一可以可靠使用回调数据的位置是在回调内部或在回调内部被调用的位置。

您可以在此处了解有关异步/回调问题的详细信息: 在函数内部修改变量后,为什么变量没有改变? -异步代码参考

要知道所有这些createOrUpdateMarket()操作createOrUpdateMarket()全部完成,您将必须编写代码,尤其是要知道所有这些操作何时完成并且不能依赖简单的for循环。 现代的方法是使用promise,promise提供工具来帮助您管理一个或多个异步操作的时序。

另外,如果要在marketArray累积来自for循环的marketArray ,则必须在for循环之前for不是for循环内声明并初始化它。 以下是几种解决方案:

手动编码解决方案

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

内置到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()库提供Promise.map() ,它将对您的数据数组进行迭代并产生一组异步获取的结果。

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

异步库

您还可以使用异步库来帮助管理多个异步操作。 在这种情况下,您可以使用async.map()创建一个结果数组。

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

暂无
暂无

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

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