优雅地 `async/await`


async/await 虽然取代了回调,使用类似同步的代码组织方式让代码更加简洁美观,但错误处理时需要加 try/catch

比如下面这样,一个简单的 Node.js 中使用 async/await 的场景:

const fetch = require("node-fetch");

async function getData() {
  const url = "https://api.github.com/users/wayou";
  try {
    const response = await fetch(url);
    const data = await response.json();
    console.log(data);
  } catch (error) {
    throw error;
  }
}

getData();

像这样的异步场景,Node.js 中会有很多。如果都通过 try/catch 来错误处理,数量多了之后也是不太美观的。

将异步进行一层封装

因为本质上 async/awaitPromise,我们可以封装一个简单的方法,将错误处理变得更优雅。

比如下面这样:

function await2js(promise) {
  return promise.then(result => [undefined, result]).catch(error => [error, undefined]);
}

该方法始终返回两个结果,第一个是错误,第二个是数据,这和 Node.js 中回调的入参 (err,data)=>void 是一致的,使得这层包装很 Node.js,一点也不会感到奇怪。

所以改造后的使用示例:

async function getData() {
  const url = "https://api.github.com/users/wayou";
  const [error, response] = await await2js(fetch(url));
  if (error) {
    throw error;
  }

  const [error2, data] = await await2js(response.json());
  if (error2) {
    throw error2;
  }

  console.log(data);
}

这层封装针对单个 await,不像 try/catch 那么粗犷一下子包含再次 await。也不是说 try/catch 不能精细地处理错误,但脑补一下把上面两次 await 都用 try/catch 的模样。

当然,如果嫌麻烦,也可通过 Promise.all() 或 Promise 的链式调用将多次 await 操作合并,只处理一次错误。

TypeScript 版本

function await2js<T, K = Error>(promise: Promise<T>) {
  return promise
    .then<[undefined, T]>((response: T) => [undefined, response])
    .catch<[K, undefined]>((error: K) => [error, undefined]);
}

这里有个相应的 npm 包便是做这事情的 await-to-js

相关资源

原文地址:https://www.cnblogs.com/Wayou/p/elegant_async_await.html

时间: 2024-10-02 08:38:31

优雅地 `async/await`的相关文章

如何优雅地处理Async/Await的异常?

译者按: 使用.catch()来捕获所有的异常 原文: Async Await Error Handling in JavaScript 译者: Fundebug 本文采用意译,版权归原作者所有 async/await 中的异常处理很让人混乱.尽管有很多种方式来应对async 函数的异常,但是连经验丰富的开发者有时候也会搞错. 假设你有一个叫做run()的异步函数.在本文中,我会描述 3 种方式来处理run()的异常情形: try/catch, Go 语言风格, 函数调用的时候使用 catch(

ES6 async/await语法

Async/await的主要益处是可以避免回调地狱(callback hell)问题 Chromium JavaScript引擎 从v5.5开始支持async/await功能,Chromium JavaScript引擎版本号的查看方法是:在浏览器地址栏输入 chrome://version,查询出来的信息如下图所示: 这意味着async/await不再是实验性功能,使用它时无需指定--harmony参数,此参数用来开启那些几乎已完成但被V8团队认为还不稳定的功能.不同的node版本使用不同的V8

进阶篇:以IL为剑,直指async/await

接上篇:30分钟?不需要,轻松读懂IL,这篇主要从IL入手来理解async/await的工作原理. 先简单介绍下async/await,这是.net 4.5引入的语法糖,配合Task使用可以非常优雅的写异步操作代码,它本身并不会去创建一个新线程,线程的工作还是由Task来做,async/await只是让开发人员以直观的方式写异步操作代码,而不像以前那样到处都是callback或事件. async/await IL翻译 先写个简单的例子: 1 using System; 2 using Syste

callback vs async.js vs promise vs async / await

需求: A.依次读取 A|B|C 三个文件,如果有失败,则立即终止. B.同时读取 A|B|C 三个文件,如果有失败,则立即终止. 一.callback 需求A: let read = function (code) { if (code) { return true; } else { return false; } } let readFileA = function (callback) { if (read(1)) { return callback(null, "111");

promise/async/await

promise和async/await都是异步方案,promise是es6的新特性,而async/await是es7新出的特性.而对于async/await来说是基于promise的,他可以让我们更加优雅的写出代码,而替代then()的写法,例如: const f = () => { return new Promise((resolve, reject) => { setTimeout(() => { reject(234); }, 2000); }); }; const testAs

拒绝回调,拥抱async await

之前使用jquery中ajax,请求的结果需要写在回调函数里面,后面接触到了axios/fetch,使用了es6中Promise进行封装,这种链式结构调用,看起来比之前直观,可是还是没有解决需要把结果写在回调函数里面,甚至axios/fetch相比原生ajax以及jquery中的ajax来说,不支持同步请求,这就导致:当一个请求需要的参数是依赖上一次请求返回的结果时,只能把第二次请求也写在第一次请求的回调里面,当内容过多时,就会被嵌套绕进去,写法上很不优雅. es7中的async await正是

现代JS中的流程控制:详解Callbacks 、Promises 、Async/Await

JavaScript经常声称是_异步_.那是什么意思?它如何影响发展?近年来这种方法有何变化? 请思考以下代码: result1 = doSomething1(); result2 = doSomething2(result1); 大多数语言都处理每一行同步.第一行运行并返回结果.第二行在第一行完成后运行无论需要多长时间. 单线程处理 JavaScript在单个处理线程上运行.在浏览器选项卡中执行时,其他所有内容都会停止,因为在并行线程上不会发生对页面DOM的更改;将一个线程重定向到另一个URL

细说 async/await 相较于 Promise 的优势

async 函数是什么?谈及异步回调函数的嵌套,总会让人感到烦躁,特别是当业务逻辑复杂,往往需要调用几次 ajax 才能拿到所有需要的数据.从最早的回调函数,到 Promise 对象,再到 Generator 函数,每次都有所改进,但又让人觉得不彻底.它们都有额外的复杂性,都需要理解抽象的底层运行机制.所以,我们需要一种方法,更优雅地解决异步操作.于是,async函数出现了.一句话解释:async 函数,就是 Generator 函数的语法糖.它有以下几个特点: 建立在 promise 之上.所

js中promise解决callback回调地狱以及使用async+await异步处理的方法

1.callback回调地狱 function ajax(fn) { setTimeout(()=> { console.log('你好') fn() }, 1000) } ajax(() => { console.log('执行结束') ajax(()=>{ console.log('执行结束') ajax(()=>{ console.log('执行结束') ajax(()=>{ console.log('执行结束') }) }) }) }) 2.promise解决回调地狱