如何处理一个大数组应用nodejs中的每个元素的asynchronous函数?

我正在与zombie.js刮一个网站,我必须使用callback风格来连接到每个url。 重点是我有一个urls数组,我需要使用asynchronous函数来处理每个url。 这是我的第一个方法:

Array urls = {http..., http...}; function process_url(index) { if(index == urls.length) return; async_function(url, function() { ... //parse the url ... // Process the next url process_url(index++); } ); } process_url(0) 

如果没有使用第三方nodejs库来使用asyn函数作为同步函数或等待函数(wait.for,synchornized,mocha),这是我通过解决这个问题的方式,我不知道会是什么如果数组太大,就会发生。 当下一个函数被调用时,函数是否从内存中释放? 或者所有的function都在内存中,直到结束?

有任何想法吗?

你的计划将起作用。 我称之为“手动sortingasynchronous操作”。

你正在做的通用版本是这样的:

 function processItem(data, callback) { // do your async function here // for example, let's suppose it was an http request using the request module request(data, callback); } function processArray(array, fn) { var index = 0; function next() { if (index < array.length) { fn(array[index++], function(err, result) { // process error here if (err) return; // process result here next(); }); } } next(); } processArray(arr, processItem); 

至于你的具体问题:

如果arrays太大,我不知道会发生什么。 当下一个函数被调用时,函数是否从内存中释放? 或者所有的function都在内存中,直到结束?

当Javascript中的内存不再被任何正在运行的代码引用,并且垃圾收集器有时间运行时,它就会被释放。 由于您正在运行一系列asynchronous操作,所以垃圾收集器可能有机会在等待asynchronous操作的http响应的同时定期运行,以便内存得到清理。 函数只是Javascript中的另一种types的对象,它们像其他任何东西一样被垃圾回收。 当他们不再被运行代码引用时,他们有资格进行垃圾回收。

在你的特定代码中,因为你只是在asynchronouscallback中重新调用process_url() ,所以没有堆积(正常recursion)。 process_url()的前一个实例在调用asynchronouscallback之前已经完成,并且在调用process_url()的下一个迭代之前。


一般来说,使用当前版本的node.js中内置的promise,多个asynchronous操作的pipe理和协调是非常容易的,并且是ES6 ECMAScript标准的一部分。 在当前版本的node.js中,不需要外部库来使用promise。

有关使用承诺而不使用承诺的数组sorting操作的许多不同技术的列表,请参见:

如何同步一系列的承诺? 。

使用承诺的第一步是“promisify”你的asynchronous函数,以便它返回一个承诺,而不是一个callback。

 function async_function_promise(url) { return new Promise(function(resolve, reject) { async_function(url, function(err, result) { if (err) { reject(err); } else { resolve(result); } }); }); } 

现在,你有一个返回promise的函数版本。

如果你希望你的asynchronous操作一次执行一个,所以下一个操作直到前一个操作完成才会启动,那么通常的devise模式就是使用.reduce()这样的操作:

 function process_urls(array) { return array.reduce(function(p, url) { return p.then(function(priorResult) { return async_function_promise(url); }); }, Promise.resolve()); } 

那么,你可以这样调用它:

 var myArray = ["url1", "url2", ...]; process_urls(myArray).then(function(finalResult) { // all of them are done here }, function(err) { // error here }); 

也有Promise库有一些有用的function,使这种types的编码更简单。 我自己使用蓝鸟承诺库。 下面是你的代码使用Bluebird的样子:

 var Promise = require('bluebird'); var async_function_promise = Promise.promisify(async_function); function process_urls(array) { return Promise.map(array, async_function_promise, {concurrency: 1}); } process_urls(myArray).then(function(allResults) { // all of them are done here and allResults is an array of the results }, function(err) { // error here }); 

请注意,您可以将concurrency值更改为此处所需的值。 例如,如果将其增加到25之间(取决于服务器如何实现最佳优化),您可能会获得更快的端到端性能。