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

Javascript While循环中的承诺,其中While的条件基于承诺的结果,javascript,es6-promise,Javascript,Es6 Promise,我需要做一个不确定的循环,其中循环的条件将基于循环中从数据库获取一些数据的承诺的响应。循环应该在一个promise中完成,该promise返回从数据库中提取的记录的总列表。这与真实世界的示例相比有些简化,但我尝试提供一些基本代码来演示我基本上想要做的事情 对getLinkedEntitys的调用传入一个实体,并基于链接实体id开始循环,在该循环中返回链接实体,然后从原始承诺返回 我遇到的问题是,由于承诺的异步性质,在while循环中调用getElement的那一刻,它永远不会解决问题,因为函数会

我需要做一个不确定的循环,其中循环的条件将基于循环中从数据库获取一些数据的承诺的响应。循环应该在一个promise中完成,该promise返回从数据库中提取的记录的总列表。这与真实世界的示例相比有些简化,但我尝试提供一些基本代码来演示我基本上想要做的事情

对getLinkedEntitys的调用传入一个实体,并基于链接实体id开始循环,在该循环中返回链接实体,然后从原始承诺返回

我遇到的问题是,由于承诺的异步性质,在while循环中调用getElement的那一刻,它永远不会解决问题,因为函数会继续,并卡在连续循环中

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

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

如果不使用
async/await
,您可以创建一个内部函数来调用自己

例如

基本上,这只是继续调用
getNext
,直到设置了
stopLoop
,然后解析
linkedEntities
,否则它会再次调用
getNext
。IOW:这正是while循环所做的

下面是一个使用这个想法的工作片段,我用睡眠承诺代替了
getElement
。基本上,每个阵列推送之间有一个500毫秒等待的阵列

功能睡眠(毫秒){
返回新承诺(函数(解析){
设置超时(解析,毫秒);
});
}
功能测试(){
var-ret=[];
函数getNext(){
返回睡眠(500)。然后返回(函数(){
如果(返回长度>=10){
返回ret;
}否则{
console.log('tick:'+ret.length);
回推(回推长度+1);
返回getNext();
}
});
}
返回getNext();
}
test()。然后(函数(r){
console.log('Resolved with->');
log(r.join(',);

});您想要使用的可能是setInterval或setTimeout,而不是while循环。对于setInterval,请不要忘记清理。当间隔需要允许可能需要不确定长度的数据库调用时,这不是问题吗?setInterval将每X毫秒触发一次该方法。只要页面以AIK方式加载,它就可以永远运行。这就是为什么一旦问题解决,你就必须清理它。setTimeout将在X毫秒后仅触发一次。如果条件未满足,您可以在处理程序中设置另一个超时。这可以通过从函数本身调用函数来完成。但是如果你可以使用
async/await
就容易多了,而且你可以保留while逻辑。可以使用
async
/
await
或递归函数。也许我误解了承诺的工作原理,但是当我尝试这样做的时候,对getElement的第一次调用解决了,对getNext中的回调是异步的,永远不要开枪,马上行动returns@StewartAlan
getNext
将始终立即返回。但是它会返回一个承诺,从这个承诺中,您可以得到
然后
able,回调。基本上,我们正在做的是承诺链。请注意:确保您
返回
,否则承诺链接将失败。我仍然感到困惑。我有一个外部承诺,需要解析LinkedEntitys数组的最终值。您能否提供一个代码示例,其中该承诺执行getNext,直到stopLoop为true才解析。诚然,我对承诺并不熟悉,我觉得这有点难以理解around@StewartAlan我已经创建了一个工作片段供您查看,它基本上与您的after的工作方式相同。我可以确认代码按预期工作,但它唯一起作用的原因是睡眠承诺中的强制超时,所以我仍然不确定这对我有什么帮助。在我的例子中,当您调用sleep时,我需要调用查询数据库并解析结果的现有Promise。我仍然不知道如何以同步方式使用您的代码来实现这一点。
  ...
  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();
}