调用asynchronous函数只能在callbacknodejs中完成一次

我有代码,以某种方式接收100000数据集。 然后有一个存储必须被访问的方式,只有最后一个添加完成后,下一个可以开始。

以同步的方式,看起来像这样..所以添加方法会阻止。

var data = [...]; //100000 datasets var syncstorage = require( 'syncstorage' ); // syncronous storage. for( var i = 0 ; i < data.length() ; i++ ) { syncstorage.add( data[i] ); // will only return once stored } 

asynchronous存储不阻止,但它会告诉你什么时候完成callback…

 /////// async storage asyncstorage.add( data[i] , function(err) { /* can only execute another add once i get this response */ } ) 

现在我只想到了这个:

 var i = 0; function execute() { if( i >= data.length()){ return; } asyncstorage.add( data[i] , function(err) { i++; execute(); } ) } 

然而这会导致一个极端的调用堆栈

也许我会需要一个事件发射器,并在该callback中发出它? 还有一个资源包装? 这是如何解决? …我很遗憾没有find关于这个具体问题堆栈溢出的结果;

排除了解决办法

  • async.each
    • http://caolan.github.io/async/docs.html#.each
    • “这个函数并行迭代到每个项目”
  • async.series
    • http://caolan.github.io/async/docs.html#.series
      1. 它需要一系列不是数据的function
      1. 它将需要从callback调用的callback,而不是也准备并行运行
    • 所以它可以使用,但只有在不成比例的内存要求(function)
    • 也不知道如何asynchronous处理这个内部(调用堆栈明智)

testing例子

 var store = {add:function(d,cb){cb(null)}}; var d=[]; for(var i = 0 ; i < 100000; i ++) { d.push(i)}; d; var async = require('async'); async.eachSeries(d,store.add); 

不起作用! 这是因为asynchronous假定迭代函数中会有一个事件发射器。 因此像上面这样一个简单的testing类在Maximum call stack size exceeded

使用承诺或asynchronous

 var async = require('async'); // Assuming that asyncstorage.add = function(chunk, callback) { ... } async.eachSeries(data, asyncstorage.add, function(err) { if (err) console.log(err); ... }); 

删除Maximum call stack size exceeded的决定是调用nextTick 。 这是“给node.js清除堆栈的机会( 阅读更多 )”。

改进的代码
asynchronous

 var async = require('async'); var store = { add: function(chunk, cb){ res.push(chunk); cb(null); } }; var data = []; for (var i = 0 ; i < 100000; i ++) data.push(i); var res = []; // for test result async.eachSeries(data, // on each iteration. function f(chunk, cb) { async.nextTick(function() { store.add(chunk, cb) }); }, // on done function(err) { console.log((err) ? err : ('done ' + res.length)); } ); 

活动Emmiter

 var data = []; for (var i = 0; i < 100500; i++) data.push(i); var store = { add: function (chunk, cb) { cb(null); } }; var EventEmitter = require('events').EventEmitter; var e = new EventEmitter; e.on('next', function(i) { if (i > data.length) return console.log(i, 'done'); setImmediate(function() { // clear stack store.add(data[i], () => e.emit('next', i + 1)) }); }) e.emit('next', 0);