我有一个异步函数'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”似乎是一个坏方法,而且我还必须使其工作,以便它可以传递先前then语句中的数据。我想做的是在“ doApiRequest”本身内部处理此问题。

'doApiRequest'看起来像这样

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


但是,我试图找到一种不涉及嵌套Promises的方法。还有什么其他方法可以解决这个问题。我执行此操作的另一种方法是使用Async / Await,是否还有其他仅凭承诺进行操作的方法?从(doApiRequest)返回带有附加的then函数的Promise会发生什么(甚至可能),例如...

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


在原来的then函数中,调用了doApiRequest的函数将接收由waitForRateRefresh返回的值,或者向下遍历附加到它的then链的结果。

感谢您的任何见解

最佳答案

虽然async / await很棒,但是如果您使用的是不支持它的旧版本的nodejs,那么您要么需要转译async/await代码,要么使用普通的Promises

不知道您是否曾经看过转译的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中接受来自doSomething的值,请将代码更改为

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


现在的主要代码

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


同样,尽管...如果//http call是异步收集在return someValue中的任何内容,则someValuehttp 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的函数中

关于javascript - 避免在then函数JS中嵌套 promise ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49744219/

10-11 09:32