多次调用含Promise的show函数后仅首次触发resolve方法的原因
问题:为何Promise的resolve回调仅首次执行?
代码示例
var i = 1; var x; var z = 1 setTimeout(show, 8000); setTimeout(show, 4000); show(); function show() { console.log("Hello,show was called:- ", z); //to check if control is going inside show() function z++; x = new Promise(function (resolve, reject) { setTimeout(function () { if (i >= 1) resolve(); else reject(); }, 1000); }); } x .then( () => { console.log("Resolve was called:- ", i); i++; } ) .catch( () => { console.log("Wrong limit"); } )
运行输出
Hello,show was called:- 1 Resolve was called:- 1 Hello,show was called:- 2 Hello,show was called:- 3
原因分析
核心问题在于变量x被重复赋值,且只有第一次赋值的Promise绑定了.then/.catch回调:
- 首次调用
show()时,x被赋值为第一个Promise对象,后续代码中的x.then(...)为这个Promise注册了resolve回调。1秒后该Promise resolve,触发回调输出日志。 - 4秒后第二次调用
show(),x被覆盖为一个全新的Promise,但这个新Promise没有绑定任何.then/.catch回调。即使1秒后它成功resolve,也没有对应的回调函数可以执行。 - 8秒后第三次调用
show()同理,x再次被替换为新的Promise,同样未注册回调,因此不会输出resolve相关日志。
修复方案
如果希望每次调用show()时,内部创建的Promise都能触发回调,有两种常见方式:
- 在
show()函数内部,为当前创建的Promise直接绑定回调:
function show() { console.log("Hello,show was called:- ", z); z++; // 直接为当前Promise绑定回调 new Promise(function (resolve, reject) { setTimeout(function () { if (i >= 1) resolve(); else reject(); }, 1000); }) .then(() => { console.log("Resolve was called:- ", i); i++; }) .catch(() => { console.log("Wrong limit"); }); }
- 避免覆盖
x,而是每次将新Promise存入数组,统一处理(如果需要批量操作):
var i = 1; var promises = []; // 用数组存储所有Promise var z = 1 setTimeout(show, 8000); setTimeout(show, 4000); show(); function show() { console.log("Hello,show was called:- ", z); z++; const p = new Promise(function (resolve, reject) { setTimeout(function () { if (i >= 1) resolve(); else reject(); }, 1000); }); promises.push(p); // 存入数组 } // 遍历数组为每个Promise绑定回调 promises.forEach(p => { p.then(() => { console.log("Resolve was called:- ", i); i++; }) .catch(() => { console.log("Wrong limit"); }); });
内容的提问来源于stack exchange,提问作者Brijesh Roy
相关产品推荐
相关产品推荐

