递归链接 Promise [英] Chaining Promises recursively

查看:22
本文介绍了递归链接 Promise的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个简单的 Windows 8 应用程序,我需要在其中从网站获取一组数据.我正在使用 WinJS.xhr() 来检索此数据,它返回一个 Promise.然后我将一个回调传递给这个 Promise 的 .then() 方法,它为我的回调提供异步调用的返回值..then() 方法返回另一个 Promise,给它我的回调返回的值.这种查询的基本结构如下:

I'm working on a simple Windows 8 app in which I need to fetch a set of data from a web site. I am using WinJS.xhr() to retrieve this data, which returns a Promise. I then pass a callback into this Promise's .then() method, which supplies my callback with the returned value from the asynchronous call. The .then() method returns another Promise, giving it the value that my callback returns. The basic structure of such a query would be as follows:

WinJS.xhr({ url: "http://www.example.com/" }).then(
    function callback( result_from_xhr )
    {
        //do stuff
        return some_value;
    }).then(
    function secondcallback( some_value )
    {
        //do stuff
    });

但是,在我的情况下,我可能需要根据第一个查询返回的数据对数据进行其他查询,并且可能需要根据 THAT 数据进行更多查询......等等,递归.

In my situation, however, I may need to make additional queries for data depending on the data returned by the first query, and possibly more queries depending on THAT data... and so on, recursively.

我需要一种编码方法,以便在所有递归完成之前不执行最终的 .then(),类似于:

I need a way to code this such that the final .then() is not executed until ALL the recursions have completed, similar to this:

function recurse() {
    return WinJS.xhr({ url: "http://www.example.com/" }).then(
        function callback( result_from_xhr )
        {
            if( result_from_xhr == something )
            {
               recurse();
            }
        });
}

recurse().then(
function final()
{
    //finishing code
});

问题是,当然,一旦第一级递归完成,就会调用完成代码.我需要某种方式在回调中嵌套新承诺和旧承诺.

The problem is that, of course, the finishing code is called as soon as the first level of recursion completes. I need some way to nest the new promise and the old promise from within the callback.

我希望我的问题足够清楚,我真的不知道如何解释它,坦率地说,异步递归代码的想法让我很头疼.

I hope my question is clear enough, I'm really not sure how to explain it and frankly the idea of asynchronous recursive code makes my head hurt.

推荐答案

我在这里要做的是创建一个全新的、独立的 promise,您可以手动完成它,并从 recurse() 函数返回它.然后,当您知道自己已完成异步工作时,请完成该承诺.

What I would do here is to create a whole new, standalone promise that you can complete manually, and return that from the recurse() function. Then, when you hit the point that you know you're done doing async work, complete that promise.

Promise.join 在您有一组已知的承诺时起作用 - 在调用 join 之前,您需要整个可用的承诺数组.如果我遵循最初的问题,那么您将拥有可变数量的承诺,更有可能作为异步工作的一部分出现.在这些情况下,加入不是正确的工具.

Promise.join works when you've got a known set of promises - you need the entire array of promises available before you call join. If I followed the original question, you have a variable number of promises, with more possibly popping up as part of async work. Join isn't the right tool in these circumstances.

那么,这看起来像什么?像这样:

So, what does this look like? Something like this:

function doSomethingAsync() {
  return new WinJS.Promise(function (resolve, reject) {
    function recurse() {
      WinJS.xhr({ url: "http://www.example.com/" })
        .then(function onResult(result_from_xhr) {
          if (result_from_xhr === something) {
            recurse();
          } else {
            // Done with processing, trigger the final promise
            resolve(whateverValue);
          },
          function onError(err) {
            // Fail everything if one of the requests fails, may not be
            // the right thing depending on your requirements
            reject(err);
          });
    }
    // Kick off the async work
    recurse();
  });
}

doSomethingAsync().then(
function final()
{
    //finishing code
});

我重新安排了递归发生的位置,这样我们就不会每次都重新创建一个新的承诺,因此使用嵌套的 recurse() 函数而不是在外层使用它.

I rearranged where the recursion is happening so that we aren't recreating a new promise every time, thus the nested recurse() function instead of having it at the outer level.

这篇关于递归链接 Promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆