如何确保Promise链中if-else后的rp异步操作完成后再执行后续函数?
解决Promise链中异步操作导致后续逻辑提前执行的问题
我一眼就看出问题所在了——你的repeat函数里,当进入!result分支调用rp的时候,没有把rp返回的Promise对象返回出去,这就导致这部分异步操作脱离了整个Promise链的控制。Promise链会认为repeat在这里已经完成了,直接继续往下走调用doOther(),而rp的逻辑还在后台异步执行,自然就出现了你看到的顺序混乱。
具体问题点
在这段代码里:
if (!result) { console.log("step 7"); rp(url).then(data => { // ...后续逻辑 }); }
你调用了rp(url)但没有返回它,所以这个异步任务没有被加入到当前的Promise链中。repeat函数的Promise会在执行到这里的时候直接默认resolve,导致上游的.then(() => doOther())提前触发。
修改方案
只需要把rp(url)的调用返回出去,让它成为Promise链的一部分,这样整个流程就会等待rp及其内部的所有异步逻辑完成后,才会继续往下走。同时,还要确保repeat函数里所有分支都返回Promise或者值,保证链的完整性。
修改后的完整代码:
const request = require("request"); const rp = require("request-promise"); let url = "http://localhost:3000/"; let sendResult = c => { console.log("step 4", c); return new Promise((resolve, reject) => { if (c < 5) { console.log("step 5 resolve(true)", c); resolve(true); } else { console.log("step 5 resolve(false)", c); resolve(false); } }); }; let repeat = (a, b) => { const c = a + b; // 加上const避免全局变量污染 console.log("step 3", c); return sendResult(c).then(result => { console.log("step 6", result); if (!result) { console.log("step 7"); // 关键修改:返回rp的Promise,把它纳入链中 return rp(url).then(data => { console.log("step 8"); let d = c + 1; if (d < 7) { console.log("step 9", d); return repeat(d, a); } else { console.log("step 10", d); return "done"; } }); } else { return repeat(c, a); } }); }; let solveProblem = (a, b) => { return new Promise((resolve, reject) => { resolve(a + b); }); }; let doOther = () => { console.log("doOther"); }; let run = (a, b) => { console.log("step 1"); solveProblem(a, b) .then(data => { console.log("step 2", data); return repeat(data, 1); }) .then(() => { return doOther(); }); }; run(1, 1);
修改后的执行流程
现在整个Promise链会严格等待所有异步操作完成:
- step 1
- step 2 2
- step 3 3
- step 4 3
- step 5 resolve(true) 3
- step 6 true
- step 3 5
- step 4 5
- step 5 resolve(false) 5
- step 6 false
- step 7
- step 8
- step 9 6
- step 3 9
- step 4 9
- step 5 resolve(false) 9
- step 6 false
- step 7
- step 8
- step 10 10
- doOther
这样就完全符合你预期的流程了——所有repeat里的异步逻辑(包括rp调用)都完成后,才会执行doOther()。
另外提个小建议:repeat里的c变量最好加上const,避免不小心变成全局变量,这是个良好的编码习惯。
内容的提问来源于stack exchange,提问作者davislf2
相关产品推荐
相关产品推荐

