在包含100000条记录的以下代码中,recursiveFnReturnsPromiseV1执行正常,而recursiveFnReturnsPromiseV2因堆栈外异常而失败。两者之间的唯一区别是承诺被递归的方式。在v1中,递归在第一个promise的“then”内,而在v2中,递归在原始promise本身内。有什么区别?
let aValues = Array(100000);
recursiveFnReturnsPromiseV1(aValues, 0).then(function() {
let p = document.createElement('div');
p.innerText = 'recursiveFnReturnsPromiseV1 finished';
document.getElementById('v1').appendChild(p);
}, function() {
let p = document.createElement('div');
p.innerText = 'recursiveFnReturnsPromiseV1 failed';
document.getElementById('v1').appendChild(p);
})
recursiveFnReturnsPromiseV2(aValues, 0)
.then(function() {
let p = document.createElement('div');
p.innerText = 'recursiveFnReturnsPromiseV2 finished';
document.getElementById('v2').appendChild(p);
}, function() {
let p = document.createElement('div');
p.innerText = 'recursiveFnReturnsPromiseV2 failed';
document.getElementById('v2').appendChild(p);
})
function recursiveFnReturnsPromiseV1(pValues, ix) {
if (pValues.length <= ix)
return Promise.resolve();
return new Promise(function(c, e) {
document.getElementById('v1').innerText = ix + 'v1' + Date.now();
c();
}).then(function() {
return recursiveFnReturnsPromiseV1(pValues, ++ix);
})
}
function recursiveFnReturnsPromiseV2(pValues, ix) {
if (pValues.length <= ix)
return Promise.resolve();
return new Promise(function(c, e) {
document.getElementById('v2').innerText = ix + 'v2' + Date.now();
recursiveFnReturnsPromiseV2(pValues, ++ix).then(function() {
c();
}, function(err) {
e()
});
})
}
<div id='v1'></div>
<div id='v2'></div>
答案 0 :(得分:1)
让我们剥离Promise
constructor antipattern,然后使用简单的Promise.resolve
。您的功能现在变为
function recursiveFnReturnsPromiseV1(pValues, ix) {
if (pValues.length <= ix)
return Promise.resolve();
let p = document.createElement('div');
p.innerText = ix + 'v1' + Date.now();
document.getElementById('v1').appendChild(p);
return Promise.resolve().then(function() {
return recursiveFnReturnsPromiseV1(pValues, ++ix);
})
}
function recursiveFnReturnsPromiseV2(pValues, ix) {
if (pValues.length <= ix)
return Promise.resolve();
let p = document.createElement('div');
p.innerText = ix + 'v2' + Date.now();
document.getElementById('v2').appendChild(p);
return Promise.resolve(recursiveFnReturnsPromiseV2(pValues, ++ix));
}
现在应该很清楚为什么第二个函数会溢出堆栈。
为什么第一个也不是?因为递归调用是在异步 then
回调中,这意味着它在稍后(在外部调用返回之后)使用新的调用堆栈启动。