【问题标题】:Async mixed with standard callback异步与标准回调混合
【发布时间】:2020-04-12 09:24:08
【问题描述】:

我刚开始学习 Javascript 中的Promises,碰巧遇到了async/await

据我了解,如果我指定一个函数为async,javascript 将始终包装我的函数内容并返回Promise,而不是我返回的任何内容。

让我们假设以下场景:

async function httpRequest() {
   oReq = new XMLHttpRequest();
   oReq.addEventListener("load", function() {
      return this.responseText;
   });

   oReq.open("GET", "http://some.url.here");
   oReq.send();
}

httpRequest().then(function(httpResult) {
    console.log(httpResult);
}); 

我是否正确假设上述情况不起作用,因为httpRequest() 没有返回任何东西,XMLHttpRequest 的回调只返回一些东西,因此我的结果很可能是undefined

如果是,我将如何修复 httpRequest() 以便它可以在 async/await 场景中工作?

【问题讨论】:

  • httpRequest() 不需要标记为async,因为它不是await 任何东西。如果您返回异步操作,那么您可以在单独的async 函数中执行await httpRequest()
  • 它被标记为async,以便我可以在下一行中then。我想使用语言功能,它自动将我的函数包装为Promise,而不是我必须返回Promise
  • 你不需要async来使用then(),你只需要以一种或另一种方式返回一个承诺。您可以返回该承诺,或者如果您更愿意保留它async,则返回 awaited 承诺(本质上是接受一个承诺,用await 解开它,然后重新包装它)。

标签: javascript async-await es6-promise


【解决方案1】:

这里有一个执行异步操作的异步函数,该操作使用承诺。这意味着您需要设置一个函数来显式地管理和返回一个 Promise。您在这里不需要 async 关键字,因为您想明确地 return 一个您创建的 Promise,而不是 async 关键字为您创建的承诺(您无法直接管理)。

function httpRequest() {

   // Return a promise (this is what an async function does for you)
   return new Promise(resolve => {
     const oReq = new XMLHttpRequest();
     oReq.addEventListener("load", function() {

        // Resolve the promise when the async operation is complete.
        resolve(this.responseText);
     });

     oReq.open("GET", "http://some.url.here");
     oReq.send();
   };
}

现在该函数显式返回一个承诺,它可以是awaited,就像async 函数一样。或者像任何承诺一样与then() 一起使用。

async function someFunction() {
  // await
  const awaitedResponse = await httpRequest();
  console.log(awaitedResponse);

  // or promise chain
  httpRequest().then(responseText => console.log(responseText));
};

【讨论】:

  • You can't actually use the async keyword here, since you nee to actually return a Promise. - 当然你仍然可以使用 async 关键字并返回承诺,这只是多余的
  • 老兄,我听说你喜欢承诺。所以我返回了一个承诺,它解决了一个承诺,这样你就可以在异步的同时进行异步。 也就是说,从技术上讲,你肯定可以。但这不是一件好事:)
  • Promises auto-unwrap - .then()await 都自动遵循 Promise 链,因此除了冗余之外几乎没有区别
【解决方案2】:

基本上,您正在尝试编写一个async 函数,而该函数中没有任何等待。当代码中存在一些异步时,您使用 async/await,而在您的代码中则没有。

这是一个可能有用的例子:

const getItemsAsync = async () => {
    const res = await DoSomethingAsync();
    return res.items;
}

const items = await getItemsAsync();

如您所见,DoSomethingAsync 是我等待结果的异步函数,即res。此时,代码将暂停。一旦 promise 被解析,代码将恢复,因此将返回 res.items,这意味着 items 实际上将包含异步函数的结果。

此外,async/await 只是一种空间语法,通过赋予代码更同步的形式(而非实质),使代码更具可读性。

如果你真的想让它异步,你可以承诺你的同步代码,以使它返回一个等待的承诺,然后将被解决或拒绝。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-26
    • 2017-03-19
    • 2020-07-05
    • 1970-01-01
    • 2018-10-07
    相关资源
    最近更新 更多