在While循环中承诺,其中while的条件基于承诺的结果

我需要执行一个不确定的循环,其中循环的条件将基于循环中从数据库中获取一些数据的promise的响应。循环应在一个promise中完成,然后返回从数据库中提取的记录的总列表。这与实际示例相比有所简化,但是尝试提供一些基本代码来演示我实质上要执行的操作。

对getLinkedEntities的调用在一个实体中传递,并基于一个链接的实体ID开始循环,在该循环中,将返回链接的实体,然后从原始的Promise中返回。

我遇到的问题是,由于promises的异步特性,在while循环中调用getElement的那一刻它永远无法解决,因为函数继续运行并陷入连续循环中。

希望这段代码很好地描述了我正在尝试做的事情,即最终得到了一组链接的实体,但是如何以允许所有promise返回的同步方式完成呢?

   function getLinkedEntities(startEntity) { 
        return new Promise(function (resolve,reject) {

            var linkedEntities = [];
            var entityId = startEntity.id;
            var someOtherId = startEntity.linkedentityid;

            var stopLoop = false;

            do {

                getElement(someOtherId).then(function (entity) {
                    linkedEntities.push(entity)
                    entityId = entity.id;
                    someOtherId = entity.linkedentityid;
                    stopLoop = entity.linkedentityid === null ? 1 : 0;
                });

            }
            while (!stopLoop);

            resolve(linkedEntities);

        });
    }

    function getElement(id) {
        return new Promise(function (resolve,reject) {
            // go to database and get an entity
            resolve(entity);
        });
    }

    getLinkedEntities(someEntity).then(function (response) {
        // do somethign with linkedEntities
    });
zjwmomo 回答:在While循环中承诺,其中while的条件基于承诺的结果

在不使用async / await的情况下,您可以做的是创建一个内部函数,该函数自行调用。

例如

  ...
  function getNext() {
     return getElement(someOtherId).then(function (entity) {
       linkedEntities.push(entity)
       entityId = entity.id;
       someOtherId = entity.linkedentityid;
       stopLoop = entity.linkedentityid === null ? 1 : 0;
       if (stopLoop) return resolve(linkedEntities);
       else return getNext();
     });
  }
  //boot strap the loop
  return getNext();
}

基本上,这只会一直调用getNext直到设置了stopLoop,然后解析linkedEntities,如果没有解析,它将再次调用getNext。 IOW:您的while循环到底在做什么。

下面是使用此想法的有效代码段,我已经用睡眠承诺代替了getElement。基本上,每次阵列推送之间要等待500毫秒来填充阵列。

function sleep(ms) {
  return new Promise(function (resolve) {
    setTimeout(resolve,ms);
  });
}

function test() {
  var ret = [];
  function getNext() {
    return sleep(500).then(function () {
      if (ret.length >= 10) {
        return ret;
      } else {
        console.log('tick: ' + ret.length);
        ret.push(ret.length + 1);
        return getNext();
      }
    });
  }
  return getNext();
}

test().then(function (r) {
  console.log('Resolved with ->');
  console.log(r.join(','));
});

本文链接:https://www.f2er.com/2624349.html

大家都在问