【问题标题】:loop until promise function give result循环直到promise函数给出结果
【发布时间】:2017-08-28 09:34:08
【问题描述】:

我希望循环一个 promise 函数,直到得到我想要的结果。

到目前为止,我正在使用这样的递归:

function pull() {
   dataFactory.pullFunction().then(function(res) {
      pull()       
   })
}

但这给我的加载栏带来了一些前端/样式错误。

我会这样做:

function pull() {
    while (res.status == 'ONGOING') {
        dataFactory.pullFunction().then(function(res) {
            // my stuffs
        })
    }
 }

但是当我尝试它时,pullFunction() 永远不会被调用。

【问题讨论】:

  • while (res.status == 'ONGOING') - 是一个紧密的循环,如果为 true 将永远不允许任何异步代码运行,如果 false 将永远不会变为 true
  • 也许你应该更详细地描述你想要做什么。
  • 感谢您的回答,我已经编辑了我的问题
  • 所以根据我的理解,你想等到承诺完成后再做一些事情。是这样吗?
  • @Prera​​kSola 是的,我想等待承诺完成并再次循环,直到承诺结果是我正在寻找的结果

标签: javascript angularjs promise q


【解决方案1】:

如果您不能使用async/await,那么您必须使用一个调用自身的函数。这不是真正的递归,因为调用堆栈不像通常的(同步)递归那样建立。

但是,您需要始终坚持承诺。所以return 承诺,并继续使用then,在你的其余代码中初始调用pull

您可能还希望将从您的 pull 中获得的数据块收集到一个数据集中。

我在这里假设响应对象将具有包含数据块的数据属性。

这是如何工作的(使用pullFunction 的虚拟实现):

function pull() {
    return (function loop(data) {
        return dataFactory.pullFunction().then ( res => {
            return res.status === 'ONGOING'
                ? loop(data.concat(res.data))
                : data.concat(res.data)
        });
    })([]);
}

// Mock implementation
var dataFactory = {
    pullFunction: function () {
        console.log('pull');
        return new Promise( resolve => {
            setTimeout(_ =>
                resolve({
                    status: Math.random() > 0.7 ? 'DONE' : 'ONGOING',
                    data: [1,2,3,4]
                }),
            500)
        });
    }
}

// test it
pull().then( (data) => {
    console.log('data: ', data);
});
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

  • 就像您保持调用方法简洁的方式一样!你提到了“真正的递归”,你能指导我到哪里可以找到这样的学习资源吗?
  • 我没有给你参考,但请注意,当从 return 表达式中调用 loop 时,之前对 loop 的调用已经完成:仅在该调用完成之后——一些一段时间后 - 调用了 then 回调。因此,您不会有两个未完成的loop 调用实例。那是因为调用是异步发生的。在真正的递归中,调用是同步发生的,因此loop 的调用会堆积起来:当最深的调用完成时,前一个调用会继续,等等。这不会发生在这里。
【解决方案2】:

只需创建一个isOngoing 变量

let isOngoing = false;
function pull() {
  isOngoing = true;
  dataFactory.pullFunction()
    .then(res => {
      if(<your-condition>) {
        isOngoing = false;
      } else {
        pull();
      }
    })
}

编辑

你在这里处理异步操作,你不能用传统的whilefor 循环来循环它。除非您的环境允许您使用async/await 功能。

async function pull() {
    while (res.status == 'ONGOING')
        await dataFactory.pullFunction().then(function(res) {
            // my stuffs
        })
}

【讨论】:

  • 感谢您回答@jkris,但我不想使用递归
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-30
  • 2017-09-30
  • 2017-12-22
  • 2017-05-19
相关资源
最近更新 更多