前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript: 结合 async 异步函数 - 提高 Promise 的易用性

JavaScript: 结合 async 异步函数 - 提高 Promise 的易用性

作者头像
西南_张家辉
发布2021-02-02 10:11:17
7530
发布2021-02-02 10:11:17
举报
文章被收录于专栏:张家辉的树屋

前言

异步函数怎么工作的?

  • 开局一张图
image
image
代码语言:javascript
复制
async function myAsyncFunc(){
    try {
        const fulfilledValue = await promise
    }catch(rejectValue){
        console.error('error:', rejectValue)
    }
}
复制代码

函数定义之前使用了 async 关键字,就可以在函数内使用 await。 当您 await 某个 Promise 时,函数暂停执行,直至该 Promise 产生结果,并且暂停并不会阻塞主线程。 如果 Promise 执行,则会返回值。 如果 Promise 拒绝,则会抛出拒绝的值。

如何用我们的 async 改写我们的 promise 代码

  • 假如我们这里需要获取一段文字数据
代码语言:javascript
复制
function logFetch(url) {
  return fetch(url)
    .then(response => response.text())
    .then(text => {
      console.log(text);
    }).catch(err => {
      console.error('fetch failed', err);
    });
}
复制代码
  • 下面用 async 异步函数改写
代码语言:javascript
复制
async function logFetch(url) {
  try {
    const response = await fetch(url);
    
    // 打印成功获取的数据
    console.log(await response.text());
  }
  catch (err) {
  
    // 同样的抛出错误
    console.log('fetch failed', err);
  }
}
复制代码

去掉了万恶的 return 回调函数,是不是代码清爽很多了。

异步函数返回值

  • 无论是否使用 await,异步函数都会返回 Promise。该 Promise 解析时返回异步函数返回的任何值,拒绝时返回异步函数抛出的任何值。

因此,对于:

代码语言:javascript
复制
// wait ms milliseconds
function wait(ms) {
  return new Promise(r => setTimeout(r, ms));
}

async function hello() {
  await wait(500);
  return 'world';
}
复制代码

…调用 hello() 返回的 Promise 会在执行时返回 "world"。

代码语言:javascript
复制
async function foo() {
  await wait(500);
  throw Error('bar');
}
复制代码

…调用 foo() 返回的 Promise 会在拒绝时返回 Error('bar')。

如果我们想按照顺序获取数据啦?

  • 直接使用 promise
代码语言:javascript
复制
function logInOrder(urls) {
  // 先使用我们上面写好的 fetch 函数获取所有的数据
  const textPromises = urls.map(url => {
    return fetch(url).then(response => response.text());
  });

  // 然后用 reduce 把前面的 promises 一一的进行处理
  textPromises.reduce((chain, textPromise) => {
    return chain.then(() => textPromise)
      .then(text => console.log(text));
  }, Promise.resolve());
}
复制代码
  • 如果使用 async 的话
代码语言:javascript
复制
async function logInOrder(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    console.log(await response.text());
  }
}
复制代码

这样是不是简洁很多,但是这样的话我们的第二次获取数据要在第一次数据获取完毕才能开始,这样就牺牲了性能,但是我们还有更好的方法

代码语言:javascript
复制
async function logInOrder(urls) {
  // 使用 map,和 async 改写,这样可以并行获取数据
  const textPromises = urls.map(async url => {
    const response = await fetch(url);
    return response.text();
  });

  for (const textPromise of textPromises) {
    console.log(await textPromise);
  }
}
复制代码

上面的代码解决了我们并行获取数据的时间问题,又能按照我么你的需求一一按顺序打印我们的数据

使用其他语法

  • 箭头函数
代码语言:javascript
复制
const mySync = async url=> {
  try {
    const response = await fetch(url);
    console.log(await response.text());
  }
  catch (err) {
    console.log('fetch failed', err);
  }
}
  • 对象方法
代码语言:javascript
复制
const storage = {
  async getAvatar(name) {
    const cache = await caches.open('avatars');
    return cache;
  }
};

storage.getAvatar('jaffathecake').then(…);
复制代码
  • 如果情况复杂你还可以使用类来改写
代码语言:javascript
复制
class Storage {
  constructor() {
    this.cachePromise = caches.open('avatars');
  }

  async getAvatar(name) {
    const cache = await this.cachePromise;
    return cache.match(`/avatars/${name}.jpg`);
  }
}

const storage = new Storage();
storage.getAvatar('jaffathecake').then(…);
复制代码

参考

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 异步函数怎么工作的?
  • 如何用我们的 async 改写我们的 promise 代码
  • 异步函数返回值
  • 如果我们想按照顺序获取数据啦?
  • 使用其他语法
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档