JavaScript承诺停留在待处理状态

时间:2018-08-19 22:07:10

标签: javascript promise

我是Java的新手,并且怀疑我有一个基本错误。我想按顺序运行循环,但是我使用的是Promise,但它们处于“待定”状态。

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;
    });
}

我的问题与this question非常相似,除了即使我打电话给resolve()仍然停留在待处理状态。我在做什么错了?

2 个答案:

答案 0 :(得分:3)

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

更大的问题是您的while循环试图将同步循环与promises结合在一起。基本上,您的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');
});

答案 1 :(得分:1)

如果您不能使用异步/等待,则可以使用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函数将返回一个Promise(而不是一个函数),则Promise将得到解决,并且不会被顺序解决。由于我们不能保证print(1)在print(2)之前完成。它只会启动一些打印调用并以任何顺序解决。

要顺序解决承诺,我们使用以空promise开头的数组reduce,先解决它,再调用下一个promise函数。

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())