如何处理一个大数组应用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
值更改为此处所需的值。 例如,如果将其增加到2
到5
之间(取决于服务器如何实现最佳优化),您可能会获得更快的端到端性能。
- 在iisnode的web.config for Express中设置规则
- 如何在生产环境中运行Node.js + Angular 4项目
- “尝试进行NPM发布时,不能使用”新build“类的构造函数
- ubuntu pm2命令来运行node-express站点
- Angularjs从express.js的“public”文件夹的“views”文件夹中路由ejs静态文件
- var express = require('express') – 无法读取undefined的属性'prototype'
- Node.JS MVC – 在哪里放数据访问代码?
- 茉莉花忽略打字稿testing文件?
- 在我返回res.end()之后,Promise仍然会进入下一个链。