2014-02-08 35 views
0

当递归ajax函数结束递归时,我需要将一些数据粘贴到DOM中。递归Ajax延迟对象

我遇到的问题是“$ .when()。done()”会在第一步的递归中触发,但我需要在递归结束时触发递归的最后一步。

我真的不知道如何找到它,任何帮助都会好心的贬低!

function recursiveFunction(data) { 

    // do something with data 
    // and remove elements processed from data 

    var param = { 
      "data" : data 
    }; 
    return $.ajax({ 
      data: param, 
      url: 'script.php', 
      type: 'post', 
      success: function(response) { 
       recursiveFunction(response); 
      }, 
    }); 
} 

$.when(recursiveFunction(data)).done(function(response){ 
    paintData(); 
}); 

回答

2

您可以使用deffered.promise对象来处理递归执行。我修改了您的示例以提供一些数据和停止条件。例如在这里 - >jsfiddle

+0

它的工作原理就像一个魅力! – user3287601

1

关键是要简洁(而且可能仅仅)这样做是:

  • 使用外部部件为您的数据,而不是试图通过

  • 将它传递

    在递归中构建一个.then()链,使用成功路径进行递归,并为终端条件创建失败路径

  • 确保PHP脚本最终会返回HTTP错误,从而避免无限递归。

递归函数:

function recursiveFunction(response) { 
    if(response) { 
     // use `response` to act on the outer object `data` 
    } 
    return $.ajax({ 
     url: 'script.php', 
     type: 'post', 
     data: { 
      "data" : data 
     } 
    }).then(recursiveFunction); 
} 

电话如下:

var data = {'whatever':'whatever'};//this is the outer member 
recursiveFunction().fail(paintData); 

没有.when(),没有凌乱的柜台。

参见FIDDLE,其中,用于演示,使用代替$.ajax()一个setTimeout和数组作为外部构件。

+0

我需要.when(),因为我在等待2个延迟对象 – user3287601

+2

不,'.when()'用于解析两个或多个* parallel * promise。你有两个*顺序*的承诺。你的第二个'.ajax()'是在第一个成功之后创建的。 –

+0

非常好,我一直在寻找一个能够完成你所描述的功能:_sequential_ Ajax调用。我正在搜索一个非常大的数据库(数百万行),发现我可以通过分块请求来提高UX和加载时间。这导致_N_/_n_(_N_:总行数,_n_:每个块的行数)ajax调用。如果这些调用是并行发送的,则这与_N_行的一个请求相同 - 这就解决了该解决方法。谢谢甜菜根 - 甜菜根! – seebiscuit

0

如果你打算使用打字稿,你可以做如下

private updateDataNextLink(nextLinkAddress: string, outputAddress: string, defer?: JQueryDeferred<any>): JQueryPromise<string> {    
     if (defer){ 
      defer = $.Deferred();   
     } 

     DataService.retrieveSkipTokenData1(nextLinkAddress).done((tagData) => { 
      let tableData: any = ServiceContainer.officeApiHelper.createExcelTableFormat(tagData); 
      ServiceContainer.officeApi.addData(outputAddress, [], tableData.rows).done((address) => { 
       if (tagData['odata.nextLink']) { 
        ServiceContainer.officeApi.getOffsetCell(tableData.rows.length, 0, address).done((offsetAddress) => { 
         App.Instance.updateDataNextLink(tagData['odata.nextLink'], offsetAddress, defer); 
        }); 
       } else { 
        defer.resolve(address); 
       }; 
      }); 
     }); 

     return defer.promise(); 
    }