如何以不同的参数递归调用异步方法

问题描述:

我有一个使用请求模块的休息调用方法,即restRequest(),它返回异步方法的promise,我必须在得到每个结果后用不同的参数递归调用此方法并将该结果传递给相同的方法。如何以不同的参数递归调用异步方法

示例代码:

restRequest(url, "POST").then(function(response) { 
    restRequest(secondUrl, 'GET', response).then(function(response2) { 

    }): 
}); 

将其工作方式,或任何其他的东西有来解决这一点。

我会用async库这个

具体的waterfall

这将工作像

async.waterfall([ 
    function firstRequest(callback) { 

     restRequest(url, "POST").then(function(response) { 
       callback(null, response); 
     }); 
    }, 
    function secondRequest (data, callback) { 
     restRequest(secondUrl, 'GET', data).then(function(response2) { 
       callback(); 
     }); 
    } 
], function (err, result) { 
    // Handle err or result 
}); 

对不起格式化我的手机。

你可以阅读关于async.waterfall如何从上面的链接工作。

你的方法工作,但取决于你多少请求您可以用相当深幅回调地狱

但由于您使用的承诺,你可以回到你的承诺链状的最终

restRequest(url, "POST") 
.then(function(resp) { 
    return restRequest(secondUrl, "GET", resp); 
}) 
.then(function(resp) { 
    return restRequest(thirdUrl, "GET", resp); 
}); 
.then(function(resp) { 
    // do whatever keep the chain going or whatever 
}) 
.catch(function(error) { 
    // if any of the promises error it will immediately call here. 
}); 

有了承诺,您可以从.then内返回一个新的promise,并保持连锁无限。

我只是偏向于异步,因为我认为它确实提高了可读性,当正确使用时。

+0

感谢您的评论@datsik,我会检查和uDate公司 – Vivek

,你可以这样做:

let requestParams = [ 
    [url, 'POST'], 
    [secondUrl, 'GET'], 
    ... 
]; 

function callRecursive(response){ 
    if(!requestParams.length) return Promise.resolve(response); 
    let params = requestParams.shift(); 
    if(response) params.push(response); 
    return restRequest(...params).then(callRecursive); 
} 

callRecursive().then(successCallbk).catch(errCallBk); 

您可以提供一个或多个参数来bind您的部分应用功能。

restRequest(url,"POST").then(restRequest.bind(this,secondUrl, "GET")) 
         .then(restRequest.bind(this,thirdUrl, "GET")); 
+0

没了,在这里,你会最终错过了响应,参数...... – mido

由于这些串行被解雇了,你真的是一个函数(一些回报的承诺,有些人可能没有),可组成(或序列,在这里)组成一个简单的链条,我觉得这是一种整洁的方式来隔离你想要发生的一切,然后根据需要结合行为。它仍然是一个承诺之下的承诺链,但表达为一系列。首先,有几个实用方法的帮助:

var curry = (f, ...args) => 
      (f.length <= args.length) ? f(...args) : (...more) => curry(f, ...args, ...more); 
var pipeP = (...fnlist) => 
      acc => fnlist.reduce((acc,fn) => acc.then(fn), Promise.resolve(acc)); 

然后

//make restRequest only return a Promise once it's given its 3rd argument 
var restRequest = autocurry(restRequest); 

//define what our requests look like 
var request1 = restRequest('firstUrl', "POST");//-> curried function, not yet called 
var request2 = restRequest('secondUrl', 'GET');//-> curried function, not yet called 

//define some simple methods to process responses 
var extractURL = x => x.url;//-> simple function 
var extractData = x=> x.data;//-> simple function 

//final behaviors, i.e. do something with data or handle errors 
//var handleData = ... //-> do something with "data" 
//var handleError = ... //-> handle errors 

//now, create a sort of lazy program chain waiting for a starting value 
//that value is passed to request1 as its 3rd arg, starting things off 
var handleARequest = pipeP(request1, extractURL, request2, extractData); 

//and execute it as needed by passing it a starting request 
handleARequest({postdata:5}).then(handleData).catch(handleErrors); 

递归是最明显的方法,但是它没有必要。另一种方法是通过减少一系列已知参数(URL和方法)来构建一个.then()链。

该过程在“The Collection Kerfuffle”下呈现为here

function asyncSequence(params) { 
    return params.reduce(function(promise, paramObj) { 
     return promise.then(function(response) { 
      return restRequest(paramObj.url, paramObj.method, response); 
     }); 
    }, Promise.resolve(null)); // a promise resolved with the value to appear as `response` in the first iteration of the reduction. 
} 

这将满足任何数量的请求,如由params阵列的长度来确定。

电话如下:

var params = [ 
    {url:'path/1', method:'POST'}, 
    {url:'path/2', method:'GET'}, 
    {url:'path/3', method:'POST'} 
]; 

asyncSequence(params).then(function(lastResponse) { 
    //all successfully completed 
}).catch(function(e) { 
    // something went wrong 
});