链异步函数

Chain async functions

本文关键字:函数 异步      更新时间:2023-09-26

在异步函数中,我可以获得如下异步值:

const foo = await myAsyncFunction()

如果我想对结果调用一个方法,使用sync函数,我会执行类似myAsyncFunction().somethingElse() 的操作

有没有可能用异步函数链接调用,或者必须为每个结果分配一个新变量?

我更喜欢将第一个结果分配给一个中间变量,我个人觉得它更可读。

如果你愿意,你可以在表达式中等待,而不需要赋值。你所要做的就是使用括号。参见我的示例:

const foo = await (await myAsyncFunction()).somethingElseAsync()

或者,如果你想对结果调用同步方法:

const foo = (await myAsyncFunction()).somethingElseSync()

我很惊讶它还没有被提及,但在没有额外变量的情况下实现这一点的最可读的方法可能是使用.then链,而await链在最后:

await myAsyncFunction()
  .then(res => res.somethingElse())

请记住,await与承诺一起工作,但不能取代它们!

您可以尝试这个包。

  • 进程npm
  • 进程github
// Instead of thens
fetch(url)
  .then(res => res.json())
  .then(json => json.foo.bar)
  .then(value => console.log(value))
// Instead of awaits
const res = await fetch(url)
const json = await res.json()
const value = json.foo.bar
console.log(value)
// With prochain
const value = await wrap(fetch(url)).json().foo.bar
console.log(value)

Tamas Hegedus在await表达式周围用括号给出的这个答案绝对是使用普通JavaScript的方法。

或者,如果您正在寻找常见的链式JS方法,并且不介意使用第三方模块,则可以在npm上使用async af。有了它,你可以链接异步方法,比如:

const promises = [1, 2, 3].map(n => Promise.resolve(n));
AsyncAF(promises).map(n => n * 2).filter(n => n !== 4).forEach(n => console.log(n));
// logs 2 then 6
<script src="https://unpkg.com/async-af@7.0.11/index.js"></script>

如果您想每次都省略调用then(d => d.method()),可以将异步调用封装在一个小的助手函数中:

const buy = {
  cart: [],
  apple: async function() {
    setTimeout(() => {
      this.cart.push('apple');
      console.log(this.cart);
    }, 1000);
    return this;
  }
};
function chain(object, ...asyncMethods) {
  const methods = [...asyncMethods];
  methods.reduce((acc, curr) => {
    // if object is not a promise (first iteration), call the method 
    if (!acc.then) {
      const promise = curr.call(acc);
      return promise;
    } else {
      // if object is a promise, resolve it, then call the method
      return acc.then((d) => curr.call(d));
    }
  }, object);
}
chain(buy, buy.apple, buy.apple, buy.apple);
// ['apple']
// ['apple', 'apple']
// ['apple', 'apple', 'apple']

但是,如果必须将参数传递给方法,这将不起作用。在这种情况下,可以将函数调用作为对象(如{buy: "orange"})传递,然后在助手中对其进行析构函数。