Javascript 递归链接承诺

Javascript 递归链接承诺,javascript,windows-8,winjs,Javascript,Windows 8,Winjs,我正在开发一个简单的Windows8应用程序,在这个应用程序中,我需要从网站获取一组数据。我正在使用WinJS.xhr()检索此数据,它返回一个承诺。然后,我将回调传递到这个Promise的.then()方法中,该方法为回调提供异步调用返回的值。.then()方法返回另一个承诺,并将回调返回的值赋予它。这种查询的基本结构如下: WinJS.xhr({ url: "http://www.example.com/" }).then( function callback( result_fro

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

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
    });
然而,在我的情况下,我可能需要根据第一次查询返回的数据对数据进行额外的查询,并且可能需要根据该数据进行更多的查询。。。等等,递归地

我需要一种方法来编写此代码,以便在所有递归完成之前不会执行final.then(),如下所示:

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
});
当然,问题是,第一级递归完成后,就调用完成代码。我需要一些方法来嵌套回调中的新承诺和旧承诺


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

您需要使用Promise.join().done()模式。将承诺数组传递给join(),在您的情况下,这将是一组xhr调用。join()将仅在所有xhr承诺完成时调用done()。您将获得一个传递给done()的结果数组,然后可以对其进行迭代,并使用新的Promise.join().done()调用重新开始。当使用这种方法时,需要注意的是,如果传递给join()的承诺之一失败,整个操作将被视为错误条件


很抱歉,我现在没有时间尝试为您删除代码。如果有机会,我以后会努力的。但您应该能够将其插入到递归函数中并使其正常工作。

好吧,我解决了我的问题;我的递归函数误解了数据,因此从未停止过递归。感谢您的帮助,我一定会观看这些屏幕广播,因为我还没有完全掌握承诺链接结构。

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

当您拥有一组已知的承诺时,Promise.join就会起作用-在调用join之前,您需要整个承诺数组。如果我遵循最初的问题,您会有数量可变的承诺,更多的承诺可能会作为异步工作的一部分出现。在这种情况下,Join不是合适的工具

那么,这看起来像什么?大概是这样的:

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()函数不是在外部级别使用它。

在制作自己的Windows 8应用程序时,我可能以不同的方式解决了这个问题(我认为是同一个问题)

我遇到这个问题的原因是,默认情况下,对表的查询将分页,一次只返回50个结果,因此我创建了一个模式来获取前50个结果,然后获取下50个结果,以此类推,直到返回的响应结果少于50个,然后解决承诺

此代码不是真正的代码,仅用于说明:

function getAllRows() {
    return new WinJS.Promise(function(resolve, reject){

        var rows = [];

        var recursivelyGetRows = function(skipRows) {
            table.skip(skipRows).read()
                .then(function(results){
                    rows = rows.concat(results);

                    if (results.length < 50) {
                        resolve(rows);
                    } else {
                        recursivelyGetRows(skipRows + 50);
                    }
                })
        }

        recursivelyGetRows(0);

    });
}
函数getAllRows(){ 返回新的WinJS.Promise(函数(解析、拒绝){ var行=[]; var recursivelyGetRows=函数(skipRows){ 表.skip(skipRows.read()) .然后(函数(结果){ rows=rows.concat(结果); 如果(结果长度<50){ 解析(行); }否则{ 递归获取行(skipRows+50); } }) } 递归获取行(0); }); } 因此getAllRows()返回一个承诺,该承诺只有在返回结果少于50个(这表示这是最后一页)后才能解析

根据您的用例,您可能也想在其中抛出一个错误处理程序


如果不清楚,“表”是一个移动服务表。

我考虑了一种使用.join()的方法,但发现(至少按照我当时的方式)承诺会在join()调用发生后添加到数组中(因为它们是在异步调用后添加的)我将研究如何使用results数组,以及如何在递归函数中使用join,而不是out。谢谢你的建议。看看Mike Tautly的博客——有一些关于承诺的好东西。真的让我更舒服了。太棒了,创造新的承诺是我遇到的难题-你的上一句话正是我所需要的我怀疑你需要
return
语句来实现这一点,不是吗?不,它可以像看起来那样使用。getAllRows()返回一个与所有行解析的承诺。