Javascript承诺卡在挂起状态



我对Javascript很陌生,怀疑我有一个基本的错误。我想按顺序运行一个循环,但我使用的是承诺,它们停留在"挂起"状态。

function print(i){
return new Promise(function(resolve,reject){
console.log(i);
resolve();
});
}
counter = 0;
var sequence = Promise.resolve();
// The real while loop is much more complicated than this
while (counter < 10) {
sequence = sequence.then(function() {
print(counter);
}).then(function() {
counter += 1;
});
}

我的问题与这个问题非常相似,只是即使我拨打了resolve()电话,我仍然卡在待处理状态。我做错了什么?

您有两个问题。更简单的是,您不会返回print的结果,因此您永远不会等待承诺解决后再继续。

更大的问题是你的 while 循环试图将同步循环与 promise 结合起来。基本上,您的 while 循环伪代码如下所示:

while counter < 10:
spawn an async task
end

由于counter仅在异步任务中递增,因此 while 循环永远不会结束。更重要的是,由于你的while循环永远不会停止,你的异步任务永远不会启动,因为javascript是单线程的。

您可以使用await解决此问题,如下所示:

function print(i) {
return new Promise(function(resolve, reject) {
console.log(i);
resolve();
});
}
async function runLoop() {
let counter = 0;
while (counter < 10) {
const result = await print(counter);
counter += 1;
}
}
runLoop().then(() => {
console.log('done');
});

如果你不能使用 async/await,你可以使用 array.reduce 按顺序解析承诺。在这种情况下,我让 print 函数返回一个我们稍后可以调用的函数。

function print(i) {
return function() {
return new Promise(function(resolve,reject){
console.log(i);
resolve();
});
}
}

然后我们初始化我们的空 promiseArray,以及我们的计数器

const promiseArray = [];
let counter = 0;

现在我们可以向数组添加 10 个打印函数。

while (counter < 10) {
promiseArray.push(print(counter));
counter++;
}

并不是说打印函数现在返回另一个函数。我们没有调用该函数,也没有尝试解决我们的承诺。如果 print 函数返回了一个承诺(而不是函数(,则承诺将被解析,并且不会按顺序解析。因为我们不能保证 print(1( 在 print(2( 之前完成。它只会启动一些打印调用并以任何顺序解析。

为了按顺序解析承诺,我们使用数组reduce,它从一个空的承诺开始,解析它,然后调用下一个承诺函数。

promiseArray.reduce((init,curr) => {
return init.then(curr);
},Promise.resolve())

完整的代码片段如下所示:

function print(i) {
return function() {
return new Promise(function(resolve,reject){
console.log(i);
resolve();
});
}
}
const promiseArray = [];
let counter = 0;
// The real while loop is much more complicated than this
while (counter < 10) {
promiseArray.push(print(counter));
counter++;
}
promiseArray.reduce((init,curr) => {
	return init.then(curr);
},Promise.resolve())

最新更新