重构:从Promise到Async/Await

摘要: 夸张点说,技术的发展与历史一样,顺之者昌,逆之者亡。JS开发者们,赶紧拥抱Async/Await吧!

早在半年多之前,我就在鼓吹Async/Await替代Promise的6个理由,似乎还招致了一些批评。然而,直到最近,我才真正开始进行代码重构,抛弃Promise,全面使用Async/Await。因为,Node 8终于LTS了

Async/Await真的比Promise好吗?

是的是的。

这些天,我大概重构了1000行代码,最大的感觉是代码简洁了很多:

  • 真正地用同步的方式写异步代码
  • 不用写then及其回调函数,减少代码行数,也避免了代码嵌套
  • 所有异步调用可以写在同一个代码块中,无需定义多余的中间变量
  • async函数会隐式地返回一个Promise,因此可以直接return变量,无需使用Promise.resolve进行转换

下面,我们可以通过一个非常简单的示例来体验一下Async/Await的酸爽:

示例1

const Promise = require("bluebird")var readFile = Promise.promisify(require("fs").readFile)

// 使用Promisefunction usePromise(){    let a    readFile("a.txt", "utf8")        .then(tmp =>        {            a = tmp            return readFile("b.txt", "utf8")        })        .then(b =>        {            let result = a + b            console.log(result) // 输出"Hello, Fundebug!"        })

}

// 使用Async/Awaitasync function useAsyncAwait(){    let a = await readFile("a.txt", "utf8")    let b = await readFile("b.txt", "utf8")    let result = a + b    console.log(result) // 输出"Hello, Fundebug!"}

usePromise()useAsyncAwait()

由示例可知,使用Async/Await极大地简化了代码,使得代码可读性提高了非常多。

Async/Await真的替代了Promise?

是的是的。

对于Async/Await替代Promise的6个理由,批评者执着于Async/Await是基于Promise实现的,因此替代这个词不准确,这就有点尴尬了。

一方面,这里替代的是异步代码的编写方式,并非完全抛弃大家心爱的Promise,地球人都知道Async/Await是基于Promise的,不用太伤心;另一方面,Promise是基于回调函数实现的,那Promise也没有替代回调函数咯?

重构代码之后,我仍然用到了Promise库bluebird。”Talk is cheap, Show me the code!”,大家不妨看看两个示例。

示例2:Promise.promisify

使用Promise.promisify将不支持Promise的方法Promise化,调用异步接口的时候有两种方式:

const Promise = require("bluebird")var readFile = Promise.promisify(require("fs").readFile)

// 使用Promisefunction usePromise(){    readFile("b.txt", "utf8")        .then(b =>        {            console.log(b)        })}

// 使用Async/Awaitasync function useAsyncAwait(){    var b = await readFile("b.txt", "utf8")    console.log(b) // 输出"Fundebug!"}

usePromise()useAsyncAwait()

Fundebug是全栈JavaScript错误监控平台,支持各种前端和后端框架,可以帮助您第一时间发现BUG!

示例3:Promise.map

使用Promise.map读取多个文件的数据,调用异步接口的时候有两种方式:

const Promise = require("bluebird")var readFile = Promise.promisify(require("fs").readFile)var files = ["a.txt", "b.txt"]

// 使用Promisefunction usePromise(){    Promise.map(files, file =>        {            return readFile(file, "utf8")        })        .then(results =>        {            console.log(results)        })}

// 使用Async/Awaitasync function useAsyncAwait(){    var results = await Promise.map(files, file =>    {        return readFile(file, "utf8")    })    console.log(results)}

usePromise()useAsyncAwait()

没错,我的确使用了Promise库,readFile与Promise.map都是Promise函数。但是,在调用readFile与Promise.map函数时,使用Async/Await与使用Promise是两种不同写法,它们是相互替代的关系。

Async/Await有什么问题吗?

有啊有啊。

使用了await的函数定义时要加一个async,调用异步函数的时候需要加一个await,这玩意写多了也觉着烦,有时候还容易忘掉。不写async代码直接报错,不写await代码执行会出错。

示例4

const Promise = require("bluebird")var readFile = Promise.promisify(require("fs").readFile)

// 没有Asyncfunction withoutAsync(){    let b = await readFile("b.txt", "utf8") // 报错"SyntaxError: Unexpected identifier"    console.log(b) }

// 没有awaitasync function withoutAwait(){    let b = readFile("b.txt", "utf8")    console.log(b) // 打印"Promise..."}

withoutAsync()withoutAwait()

既然Async/Await写着有点添乱,可不可以不写呢?我想以后应该是可以的,只要能够自动识别异步代码就行了,这应该也是未来的发展方向。至于说如何实现,那我就不知道了哎。

总结

JavaScript的异步编写方式,从回调函数到Promise再到Async/Await,表面上只是写法的变化,本质上则是语言层的一次次抽象,让我们可以用更简单的方式实现同样的功能,而程序员不需要去考虑代码是如何执行的。在我看来,这样的进步应该不会停止,有一天我们也许不用写Async/Await了!

参考

版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2017/12/13/reconstruct-from-promise-to-async-await/

原文地址:https://www.cnblogs.com/fundebug/p/8353036.html

时间: 2024-10-08 12:04:27

重构:从Promise到Async/Await的相关文章

node.js异步控制流程 回调,事件,promise和async/await

写这个问题是因为最近看到一些初学者用回调用的不亦乐乎,最后代码左调来又调去很不直观. 首先上结论:推荐使用async/await或者co/yield,其次是promise,再次是事件,回调不要使用. 接下来是解析,为什么我会有这样的结论 首先是回调,理解上最简单,就是我把任务分配出去,当你执行完了我就能从你那里拿到结果执行相应的回调, 这里演示一个对setTimeout的封装,规定时间后打印相应结果并执行回调函数 并且这个函数传给回调函数的参数符合node标准,第一个为error信息,如果出错e

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用法整理

1.Promise 1.简介 Promise,简单来说就是一个容器,里面保存着某个未来才会结束的时间(通常是一个异步操作的结果) Promise对象的基本语法: new Promise((resolve,reject) => { //..... }); 从语法上来说,Promise是一个对象,从它可以获取异步操作的消息. 基本语法: let p = new Promise((resolve,reject) => { //... resolve('success') }); p.then(res

异步 callback vs promise vs async/await

1. callback var fn1=function(){console.log("func1")} var fn2=function(fn){ setTimeout(function(){ console.log("func2") fn() //不能写fn,这只是函数名,要写fn()才是触发 },500)}var fn3=function(){console.log("func3")} //函数名作为参数传入fn2 fn1()fn2(fn3

用promise和async/await分别实现红绿灯

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" con

promise和async/await的用法

promise和async都是做异步处理的, 使异步转为同步 1.promise 它和Promise诞生的目的都是为了解决“回调地狱”, promise使用方法: <button @click="testBtn()">点击</button> get(data) { return new Promise((resolve, reject)=>{ if (data > 5) { resolve(data); } else { reject("数

js中回调函数,promise 以及 async/await 的对比用法 对比!!!

在编程项目中,我们常需要用到回调的做法来实现部分功能,那么在js中我们有哪些方法来实现回调的? 方法1:回调函数 首先要定义这个函数,然后才能利用回调函数来调用! login: function (fn) { var app = getApp() wx.login({ success: res => { let code = res.code; wx.getSetting({ success: res => { if (res.authSetting['scope.userInfo']) {

Promise和async/await

1.promise对象 promise 对象有三种状态:pending(进行中).fulfilled(已成功)和 rejected(已失败).promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和从 pending 变为 rejected. const promise = new Promise(function(resolve, reject) { if (){ resolve(value); } else { reject(error); } });

理解异步之美:Promise与async await(一)

你可能会放出一个怪物 异步与同步相比,最难以掌控的就是异步的任务会什么时候完成和完成之后的回调问题, 难以掌控的触发状态,让你自己写的代码当时还可以读懂,但是过几天.半个月之后如果不重新盘一边逻辑,你哪知道哪个内容会先执行,借用这么一个例子 listen( "click", function handler(evt){ setTimeout( function request(){ ajax( "http://some.url.1", function respon