避免在函数JS中嵌套的promises

时间:2018-04-10 02:09:16

标签: javascript node.js promise async-await

我有一个异步函数'doApiRequest',它在'then'函数内部调用...

doSomething()
  .then(() => {
    return doApiRequest();
  })
  .then((apiResult) => {
    doSomethingElse(apiResult);
  });

问题是doApiRequest返回带有该API请求的最终结果的Promise。但是,我正在使用的API的性质是否涉及请求速率限制。我计划通过让每个API请求将自己添加到队列来处理,然后当队列在等待速率限制后释放请求时,API请求将完成解析。 虽然我可以做类似......

doSomething()
  .then(() => {
    return waitForRateRefresh();
  })
  .then(() => {
    return doApiRequest();
  })
  .then((apiResult) => {
    doSomethingElse(apiResult);
  });

我可能最终会有很多'doApiRequest'调用,因此必须在每个调用上运行'waitForRateRefresh'似乎是一个糟糕的方法而且我还必须使其工作,以便它可以传递之前的语句中的数据。我想做的是在'doApiRequest'本身内部处理这个问题。

'doApiRequest'看起来像这样

doApiRequest(){
  return new Promise((resolve, reject) => {
    waitForRateRefresh().then(() => {
      //http call
      resolve(someValue);
    };
  });
}

但是我试图找到一种不涉及嵌套Promise的方法。还有什么方法可以解决这个问题。我做的另一种方法是使用Async / Await代替,还有其他任何方式只使用promises吗?从'doApiRequest'返回带有附加then函数的Promise会发生什么(或者甚至可能)... ...

return waitForRateRefresh().then(() => new Promise(..../http call));

在调用'doApiRequest'的原始函数中 - 它将接收'waitForRateRefresh'返回的值,或者遍历附加到它的then链的结果。

感谢您的任何见解

2 个答案:

答案 0 :(得分:4)

虽然async / await很棒,但如果您使用的是不支持它的旧版本nodej,那么您需要转换async/await代码,或者使用普通的'许

不知道您是否曾见过已编译async / await - 它非常详细"详细"

您可以做什么,假设您确实要将doSomething的结果传递给doApiRequest,这是

doSomething()
.then(result => waitForRateRefresh().then(() => result))
.then((doSomethingResult) => doApiRequest(doSomethingResult))
.then((apiResult) => doSomethingElse(apiResult));

当然,上面的内容可以简化为

doSomething()
.then(result => waitForRateRefresh().then(() => result))
.then(doApiRequest)
.then(doSomethingElse);

澄清关于promise构造函数反模式的观点

doApiRequest(){
    return new Promise((resolve, reject) => {
        waitForRateRefresh().then(() => {
            //http call
            resolve(someValue);
        };
   });
}

这简化为

doApiRequest(){
    return waitForRateRefresh().then(() => {
        //http call
        return someValue;
    };
}

当然,如果// http call异常,那么就不能像return someValue那样使用doApiRequest(someResult){ return waitForRateRefresh().then(() => { //http call - use someResult here return someValue; }; } 。但是对于您的代码版本也是如此

要在此版本的doApiRequest中接受来自doSomething的值,请将代码更改为

doSomething()
.then(doApiRequest)
.then(doSomethingElse);

主要代码现在是

//http call

同样,如果return someValuesomeValuehttp call

的任何地方异步收集doApiRequest时将无法正常工作

还有一个想法,所以你不需要重写现有的功能

创建一个"包装器"在const qApiRequest = result => waitForRateRefresh().then(() => doApiRequest(result)); 附近

doSomething()
.then(qApiRequest)
.then(doSomethingElse);

现在,代码是

async

当然,await / const doSomethingResult = await doSomething(); await waitForRateRefresh(); const apiResult = doApiRequest(doSomethingResult); const finalResult = doSomethingElse(apiResult); 只是

async

当然,这些必须位于标记为thomas@abc.com

的函数中

答案 1 :(得分:1)

我会使用async/await,它可以使代码保持可读性,并且可以轻松推断下一步发生的事情。

await doSomething();
await waitForRateRefresh();
const apiResult  = await doApiRequest();
await doSomethingElse(apiResult);