节点JS:使用承诺的链接承诺

我需要链接使用请求承诺的承诺,所以它有点链接嵌套承诺。

想象一下代码:

const rp = require('request-promise'); function doStuff(){ for ( let i = 0; i <= 10; i++ ){ methodA(); } }; function methodA(){ let options = {...}; rp(options) .then(result => methodB(result)) .catch(err => console.log(err)); }; function methodB(resultA){ let options = {uri: resultA}; rp(options) .then(result => methodC(resultA, result)) .catch(err => console.log(err)); }; function methodC(resultA, resultB){ //some calculations }; 

在doStuff中,我需要等待methodC全部十次执行的结果并将它们收集到数组中。 我试图像这样链接它:

 function doStuff(){ for ( let i = 0; i <= 10; i++ ){ let promiseA = new Promise((resolve, reject) => { resolve(methodA()); }); let promiseB = promiseA.then(result => methodB(result)); let promiseC = promiseB.then(result => methodC(promiseA.result, result)); Promise.all([promiseA, promiseB, promiseC]); } }; 

但肯定它不会工作,因为在methodA和methodB我们有HTTP请求是asynchronous的。 因此,promiseB的结果是未定义的。

这意味着,问题是: 如果连锁诺言,如果他们已经嵌套承诺? (以及如何收集结果?)

谢谢!

更新:链接诺言也没有太多的帮助,因为1是AB的返回先前的数组,但预期的结果是反之亦然:

 function methodA(){ let promise = new Promise((resolve, reject) => { setTimeout(() => { console.log('Resolved A'); resolve('A'); }, Math.random() * 2000); }); return promise .then(result => methodB(result)) .catch(err => console.log(err)); } function methodB(resultA){ let promise = new Promise((resolve, reject) => { setTimeout(() => { console.log('Resolved B'); resolve('B'); }, Math.random() * 2000); }); return promise .then(result => methodC(resultA, result)) .catch(err => console.log(err)); } function methodC(resultA, resultB){ return resultA + resultB; } function doStuff() { let promises = []; for (let i = 0; i <= 10; i++){ promises.push(methodA()); } Promise.all(promises).then(results => { console.log(results); }); return 1; } console.log(doStuff()); 

你的每个函数都需要返回他们的承诺:

 function methodA(){ let options = {...}; return rp(options) .then(result => methodB(result)) .catch(err => console.log(err)); } function methodB(resultA){ let options = {uri: resultA}; return rp(options) .then(result => methodC(resultA, result)) .catch(err => console.log(err)); } function methodC(resultA, resultB){ //some calculations } function doStuff() { let promises = []; for ( let i = 0; i <= 10; i++ ){ promises.push(methodA()); } Promise.all(promises).then(...) } 

编辑:我创build了一个testing示例,它在methodBmethodB创build承诺。 每个承诺会持续0到2秒的时间。 这似乎是工作:

 function methodA(){ let promise = new Promise((resolve, reject) => { setTimeout(() => { console.log('Resolved A'); resolve('A'); }, Math.random() * 2000); }); return promise .then(result => methodB(result)) .catch(err => console.log(err)); } function methodB(resultA){ let promise = new Promise((resolve, reject) => { setTimeout(() => { console.log('Resolved B'); resolve('B'); }, Math.random() * 2000); }); return promise .then(result => methodC(resultA, result)) .catch(err => console.log(err)); } function methodC(resultA, resultB){ return resultA + resultB; } function doStuff() { let promises = []; for (let i = 0; i <= 10; i++){ promises.push(methodA()); } return Promise.all(promises).then(results => { console.log(results); return 1; }); } doStuff().then(result => { console.log(result); }); 

通过回答@Frank_Modica是要走的路。

只是想添加,如果你启用async/await你可以这样做。 但是它确实需要BabelTypescript

 async function myMethod() { const options = { } try { const result_a = await rp(options) const result_b = await rp({ uri: result_a }) const result_c = ... } catch(err) { console.log(err) } } for (let i = 0; i <= 10; i++) { await myMethod(); } 

它必须轻微改变为:

 Promise.all([promiseA, promiseB, promiseC]).then([promiseD]); 

同样在函数本身,它必须是一个返回语句,使它们链接。 对于请求本身,只需添加:{async:false}

也可以使用它:

 var runSequence = require('run-sequence'); function methodA () { return runSequence( 'promiseA', 'promiseB', ['promiseC1', 'promiseC2'], 'promiseD', callback ); }