前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >原来异步函数用起来这么“香”?不信来试试

原来异步函数用起来这么“香”?不信来试试

作者头像
公众号---人生代码
发布2021-03-16 15:19:21
发布2021-03-16 15:19:21
39300
代码可运行
举报
文章被收录于专栏:人生代码人生代码
运行总次数:0
代码可运行

今天,我们就来看看几个例子吧。

Rewrite using async/await

改写本章的示例代码,使用async/await代替.then/catch:

代码语言:javascript
代码运行次数:0
复制
function loadJson(url) {
  return fetch(url)
    .then(response => {
      if (response.status == 200) {
        return response.json();
      } else {
        throw new Error(response.status);
      }
    });
}

loadJson('no-such-user.json')
  .catch(alert); // Error: 404

改写如下:

代码语言:javascript
代码运行次数:0
复制
async function loadJson(url) { // (1)
  let response = await fetch(url); // (2)

  if (response.status == 200) {
    let json = await response.json(); // (3)
    return json;
  }

  throw new Error(response.status);
}

loadJson('no-such-user.json')
  .catch(alert); // Error: 404 (4)

注:

loadJson函数变成异步的。

所有的 .then 里面都换成了await。

我们可以返回response.json(),而不是等待它,像这样:

代码语言:javascript
代码运行次数:0
复制
if (response.status == 200) {
  return response.json(); // (3)
}

然后,外部代码将不得不等待这一承诺得到解决。在我们的情况下,这并不重要。

从loadJson抛出的错误由.catch处理。我们不能在这里使用await loadJson(…),因为我们不是在一个异步函数中。

Rewrite "rethrow" with async/await

下面是“重新抛出”的例子。用async/await代替.then/catch重写它。

并且在demoGithubUser中使用循环来摆脱递归:通过async/await,这变得很容易做到。

代码语言:javascript
代码运行次数:0
复制
class HttpError extends Error {
  constructor(response) {
    super(`${response.status} for ${response.url}`);
    this.name = 'HttpError';
    this.response = response;
  }
}

function loadJson(url) {
  return fetch(url)
    .then(response => {
      if (response.status == 200) {
        return response.json();
      } else {
        throw new HttpError(response);
      }
    });
}

// Ask for a user name until github returns a valid user
function demoGithubUser() {
  let name = prompt("Enter a name?", "iliakan");

  return loadJson(`https://api.github.com/users/${name}`)
    .then(user => {
      alert(`Full name: ${user.name}.`);
      return user;
    })
    .catch(err => {
      if (err instanceof HttpError && err.response.status == 404) {
        alert("No such user, please reenter.");
        return demoGithubUser();
      } else {
        throw err;
      }
    });
}

demoGithubUser();

这里没有什么诀窍。只要把.catch换成try…在demoGithubUser中捕获并在需要的地方添加async/await:

代码语言:javascript
代码运行次数:0
复制
class HttpError extends Error {
  constructor(response) {
    super(`${response.status} for ${response.url}`);
    this.name = 'HttpError';
    this.response = response;
  }
}

async function loadJson(url) {
  let response = await fetch(url);
  if (response.status == 200) {
    return response.json();
  } else {
    throw new HttpError(response);
  }
}

// Ask for a user name until github returns a valid user
async function demoGithubUser() {

  let user;
  while(true) {
    let name = prompt("Enter a name?", "iliakan");

    try {
      user = await loadJson(`https://api.github.com/users/${name}`);
      break; // no error, exit loop
    } catch(err) {
      if (err instanceof HttpError && err.response.status == 404) {
        // loop continues after the alert
        alert("No such user, please reenter.");
      } else {
        // unknown error, rethrow
        throw err;
      }
    }
  }


  alert(`Full name: ${user.name}.`);
  return user;
}

demoGithubUser();

Call async from non-async

我们有一个“常规”函数叫做f。你如何调用异步函数wait()并在f内部使用它的结果?

代码语言:javascript
代码运行次数:0
复制
async function wait() {
  await new Promise(resolve => setTimeout(resolve, 1000));

  return 10;
}

function f() {
  // ...what should you write here?
  // we need to call async wait() and wait to get 10
  // remember, we can't use "await"
}

这个任务在技术上非常简单,但是对于刚接触async/await的开发人员来说,这个问题是很常见的。

代码语言:javascript
代码运行次数:0
复制
async function wait() {
  await new Promise(resolve => setTimeout(resolve, 1000));

  return 10;
}

function f() {
  // shows 10 after 1 second
  wait().then(result => alert(result));
}

f();
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CryptoCode 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Rewrite using async/await
  • Rewrite "rethrow" with async/await
  • Call async from non-async
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档