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

Javascript 如何使用不同的参数递归调用异步方法,javascript,node.js,promise,protractor,es6-promise,Javascript,Node.js,Promise,Protractor,Es6 Promise,我有一个使用请求模块的rest调用方法,它是restRequest(),它以承诺的形式返回响应,这是一个异步方法,在得到每个结果并将结果传递给同一个方法之后,我必须使用不同的参数递归调用这个方法 示例代码: restRequest(url, "POST").then(function(response) { restRequest(secondUrl, 'GET', response).then(function(response2) { }): }); 这行得通吗,或者有其他的

我有一个使用请求模块的rest调用方法,它是
restRequest()
,它以承诺的形式返回响应,这是一个异步方法,在得到每个结果并将结果传递给同一个方法之后,我必须使用不同的参数递归调用这个方法

示例代码:

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

   }):
});
这行得通吗,或者有其他的方法来解决这个问题。

我会用这个库来解决这个问题

特别是
瀑布

哪一个会像

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.瀑布是如何工作的

您的方法可以工作,但取决于您有多少请求,最终可能会遇到相当深的回调地狱

但既然你在使用承诺,你就可以像这样回报你的承诺链

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. 
});
有了承诺,您可以从
中返回一个新的
承诺
。然后
,并保持链无限运行


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

您可以执行以下操作:

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);

可以为部分应用的函数提供一个或多个参数

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

由于这些函数是以串行方式启动的,所以您真正拥有的是一个简单的函数链(一些返回承诺,一些可能没有),可以组合在一起(或者这里是序列),我发现这是一种很好的方法,可以隔离出您想要发生的一切,然后根据需要组合行为。这仍然是一个承诺链下的引擎盖,但表示为一个系列。首先,有几个实用方法可以帮助您:

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));

递归是最明显的方法,但它不是必需的。另一种方法是通过减少已知参数(URL和方法)的数组来构建
.then()

该过程在“收集混乱”一节中介绍

这将满足任何数量的请求,由
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
});

谢谢@datsik的评论,我会检查并解释
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.
}
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
});