2016-05-13 4 views
7

私は約束事の配列を含んでおり、各内側配列は4k、2k、または500の約束を持つことができます。一連の約束事を連続して実行します。 Promise.allが完了したら、次のバッチに移動します

約60k約束があり、他の値でもテストすることができます。

今、私はPromise.all(BigArray [0])を実行する必要があります。

最初の内部配列が完了したら、次のPromise.all(BigArray [1])などを実行する必要があります。

私が実行しようとした場合Promise.all(BigArray)その投げ:

致命的なエラーcall_and_retry_2割当てに失敗しました - プロセスのメモリ のうち、私はシリーズの約束のそれぞれではなく、並行して、それを実行する必要があるIそれがNodeがやっていることだと思います。私は新しいlibを使用するべきではありませんが、答えを検討してください!

編集:ここでは

は、コードの例の一部です:

function getInfoForEveryInnerArgument(InnerArray) { 
    const CPTPromises = _.map(InnerArray, (argument) => getDBInfo(argument)); 
    return Promise.all(CPTPromises) 
     .then((results) => { 
      return doSomethingWithResults(results); 
     }); 
} 
function mainFunction() { 
    BigArray = [[argument1, argument2, argument3, argument4], [argument5, argument6, argument7, argument8], ....]; 
    //the summ of all arguments is over 60k... 
    const promiseArrayCombination = _.map(BigArray, (InnerArray, key) => getInfoForEveryInnerArgument(InnerArray)); 

    Promise.all(promiseArrayCombination).then((fullResults) => { 
     console.log(fullResults); 
     return fullResults; 
    }) 
} 
+0

この前の質問を投稿したのは、関連するコンテキストを含む同じユーザーですか:[Promise.allを連続して実行](http://stackoverflow.com/questions/37196699/execute-promise-all-in-series/37196780#コメント61956748_37196780)? – jfriend00

+0

すべての60k操作が並行して実行されても問題ありませんが、結果をシリアルに処理する(1つのサブ配列を一度に処理したい)だけですか?または、実際には、各サブアレイが直列に実行され、直列に処理されることを表す操作が必要ですか?後者は、node.jsのメモリとリソースの観点からはるかに安全です。 – jfriend00

+0

はい私はそうです。私はそれらを連続して走らせる必要がある。 innerArrayだけが並行して動作することを約束してOKです。 innerArray 1が完了したら、innerArray 2の次の500-4kの約束事に進み、それらを並行して実行します。innnerArray 500-4kの約束が完了するとinnerArray 3に移動し、500-4kを実行します。 innerArray 4を実行し、それらを500〜4kで実行してください...など – user1554966

答えて

6

あなたの質問は、この質問とこの質問の前のバージョンでいくつかの人々を混乱させるかもしれない少しmisnamedです。非同期操作のバッチを連続して実行しようとしています.1つの操作のバッチは完了し、別のバッチの操作を実行します。これらの非同期操作の結果は約束で追跡されます。プロミス自体は、すでに開始されている非同期操作を表します。 「約束」は自分自身では実行されません。技術的には、「一連の約束を一括して実行する」ことはありません。一連の操作を実行し、約束で結果を追跡し、最初のバッチがすべて完了したら次のバッチを実行します。

とにかく、各操作のバッチをシリアル化するためのソリューションです。

私は通常、next()と呼ばれる内部関数を作成して、各繰り返しを処理することができます。約束は1 innerArrayを処理することから解決するとき、あなたは再びnext()を呼び出す:

function mainFunction() { 
    return new Promise(function(resolve, reject) { 
     var bigArray = [[argument1, argument2, argument3, argument4], [argument5, argument6, argument7, argument8], ....]; 
     //the summ of all arguments is over 60k... 
     var results = []; 

     var index = 0; 
     function next() { 
      if (index < bigArray.length) { 
       getInfoForEveryInnerArgument(bigArray[index++]).then(function(data) { 
        results.push(data); 
        next(); 
       }, reject); 
      } else { 
       resolve(results); 
      } 
     } 
     // start first iteration 
     next(); 
    }); 
} 

これはまた、結果の配列にすべてのサブ結果を収集し、値を解決していますマスターの約束を返します。これは、配列を結果です。だから、あなたはこのように使用できます。

あなたはまた、直列配列を反復するため .reduce()デザインパターンを使用することができ
mainFunction().then(function(results) { 
    // final results array here and everything done 
}, function(err) { 
    // some error here 
}); 

function mainFunction() { 
    var bigArray = [[argument1, argument2, argument3, argument4], [argument5, argument6, argument7, argument8], ....]; 
    return bigArray.reduce(function(p, item) { 
     return p.then(function(results) { 
      return getInfoForEveryInnerArgument(item).then(function(data) { 
       results.push(data); 
       return results; 
      }) 
     }); 
    }, Promise.resolve([])); 
} 

これは最初のオプションよりも同時約束を作成し、Iそのような大規模な約束のための問題であるかどうかは分かりません(私は元のオプションを提供しています)が、このコードはより洗練されており、他の状況にも便利です。


参考までに、これを行うためのいくつかの有益なアドオン機能があります。元の配列がない約束ではなくオブジェクトである場合

function mainFunction() { 
    var bigArray = [[argument1, argument2, argument3, argument4], [argument5, argument6, argument7, argument8], ....]; 
    return Promise.map(bigArray, getInfoForEveryInnerArgument); 

} 
0

あなたがここで例えば、再帰的にそれを行うことができ、私はモンゴ約60K書類を置くために必要ですが、それはあまりにも大きかったですあなたが気づくしたい場合は、すべてが実行されたときに、

exports.rawRecursive = (arr, start) => { 
     //ending condition 
     if (start > arr.length) { 
      return; 
     } 

     Rawmedicament.insertManyAsync(_.slice(arr, start, start + 1000)).then(() => { 
      //recursive 
      exports.rawRecursive(arr, start + 1000); 
     }); 
}; 

を、1つのステップでそれを行うため、私は1kの書類を取り、モンゴに送信し、それが終了した後、私は別の1Kの文書を取るなど

しますあなたは条件コールバックを終了することができますか、またはあなたが好きであれば、あなたはresolve()を呼び出すことができます。

0

また、処理されるべきである、バッチ:(約束を使用して開発のための偉大なライブラリがある)Bluebird promise libraryで、彼らはこのために作られPromise.map()を持っています処理はArray.prototype.map()Array.prototype.slice()Promise.all()との組み合わせを使用して外部依存せずに行うことができる。

// Main batch parallelization function. 
 
function batch(tasks, pstart, atonce, runner, pos) { 
 
    if (!pos) pos = 0; 
 
    if (pos >= tasks.length) return pstart; 
 
    var p = pstart.then(function() { 
 
    output('Batch:', pos/atonce + 1); 
 
    return Promise.all(tasks.slice(pos, pos + atonce).map(function(task) { 
 
     return runner(task); 
 
    })); 
 
    }); 
 
    return batch(tasks, p, atonce, runner, pos + atonce); 
 
} 
 

 
// Output function for the example 
 
function output() { 
 
    document.getElementById("result").innerHTML += Array.prototype.slice.call(arguments).join(' ') + "<br />"; 
 
    window.scrollTo(0, document.body.scrollHeight); 
 
} 
 

 
/* 
 
* Example code. 
 
* Note: Task runner should return Promise. 
 
*/ 
 
function taskrunner(task) { 
 
    return new Promise(function(resolve, reject) { 
 
    setTimeout(function() { 
 
     output('Processed:', task.text, 'Delay:', task.delay); 
 
     resolve(); 
 
    }, task.delay); 
 
    }); 
 
} 
 

 
var taskarray = []; 
 
function populatetasks(size) { 
 
    taskarray = []; 
 
    for (var i = 0; i < size; i++) { 
 
    taskarray.push({ 
 
     delay: 500 + Math.ceil(Math.random() * 50) * 10, 
 
     text: 'Item ' + (i + 1) 
 
    }); 
 
    } 
 
} 
 

 
function clean() { 
 
    document.getElementById("result").innerHTML = ''; 
 
} 
 

 
var init = Promise.resolve(); 
 
function start() { 
 
    var bsize = parseInt(document.getElementById("batchsize").value, 10), 
 
    tsize = parseInt(document.getElementById("taskssize").value, 10); 
 
    populatetasks(tsize); 
 
    init = batch(taskarray.slice() /*tasks array*/ , init /*starting promise*/ , bsize /*batch size*/ , taskrunner /*task runner*/); 
 
}
<input type="button" onclick="start()" value="Start" /> 
 
<input type="button" onclick="clean()" value="Clear" />&nbsp;Batch size:&nbsp; 
 
<input id="batchsize" value="4" size="2"/>&nbsp;Tasks:&nbsp; 
 
<input id="taskssize" value="10" size="2"/> 
 
<pre id="result" />

+0

「再帰的でないバージョンのバッチ」については、[first edit](http://stackoverflow.com/revisions/40850909/1)を参照してください。 – Annarfych

関連する問題