我有一个使用请求模块的休息调用方法,restRequest()
返回响应作为promise,这是异步方法,我必须在获取每个结果并将结果传递给每个结果后,使用不同的参数递归调用此方法同样的方法。
示例代码:
restRequest(url, "POST").then(function(response) {
restRequest(secondUrl, 'GET', response).then(function(response2) {
}):
});
这是否有效,或者还有其他任何东西可以解决这个问题。
答案 0 :(得分:4)
我会将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的工作原理。
你的方法有效,但取决于你有多少请求你最终可能会有一个很深的回调地狱
但是既然你正在使用promises,你就可以像
一样返回你的承诺链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.
});
通过承诺,您可以在promise
内返回新的.then
,并保持链无限延伸。
我只是偏向于异步,因为我认为它确实提高了正确使用时的可读性。
答案 1 :(得分:1)
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);
答案 2 :(得分:0)
您可以向bind提供一个或多个参数到您的部分应用函数。
restRequest(url,"POST").then(restRequest.bind(this,secondUrl, "GET"))
.then(restRequest.bind(this,thirdUrl, "GET"));
答案 3 :(得分:0)
由于这些是串行发射的,你真正拥有的是一个简单的函数链(一些返回promise,有些可能没有)可以组合(或序列,在这里),我发现这是一个简洁的方法隔离出你想要发生的一切,然后根据需要组合行为。它仍然是引擎盖下的Promise链,但表现为一系列。首先,一些实用方法可以帮助:
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);
答案 4 :(得分:0)
递归是最明显的方法,但它不是必需的。另一种方法是通过减少已知参数数组(网址和方法)来构建.then()
链。
此过程在&#34; The Collection Kerfuffle&#34;下显示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
});