节点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示例,它在methodB
和methodB
创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
你可以这样做。 但是它确实需要Babel
或Typescript
:
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 ); }