温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

async/await的应用

发布时间:2020-06-15 13:46:01 来源:亿速云 阅读:256 作者:鸽子 栏目:web开发

前言

在面试的时候,async/await是很能看出应试者知识面的一个点。当然自己也没想好从什么角度去阐释这个知识点。当面试管问的时候,你可以答自执行的generator的语法糖。但是自己有些过实现么,或者是看过他的实现。

babel是如何来实现的

注:对于generator不了解的,可以先去看一下generator,顺带可以把iterator看了。

ex代码:

async function t() {
    const x = await getResult();
  	const y = await getResult2();
  	return x + y;
}

babel转化代码

"use strict";

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
    try {
        var info = gen[key](arg);
        var value = info.value;
    } catch (error) {
        reject(error);
        return;
    }
    if (info.done) {
        resolve(value);
    } else {
        Promise.resolve(value).then(_next, _throw);
    }
}

function _asyncToGenerator(fn) {
    return function () {
        var self = this, args = arguments;
        return new Promise(function (resolve, reject) {
            var gen = fn.apply(self, args);
            function _next(value) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
            }
            function _throw(err) {
                asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
            }
            _next(undefined);
        });
    };
}

function t() {
  return _t.apply(this, arguments);
}

function _t() {
  _t = _asyncToGenerator(function* () {
    const x = yield getResult();
    const y = yield getResult2();
    return x + y;
  });
  return _t.apply(this, arguments);
}

从代码中可以看出,babel将一个generator转化为async用了两步_asyncToGeneratorasyncGeneratorStep

_asyncToGenerator干了什么

1、调用_asyncToGenerator返回了一个promise,刚好符合async函数可以接then的特性。

2、定义了一个成功的方法_next,定义了一个失败的方法_throw。两个函数中是调用asyncGeneratorStep。看完asyncGeneratorStep就知道这其实是一个递归。

3、执行_next。也就是上面说的自执行的generator。

asyncGeneratorStep干了什么

1、try-catch去捕获generator执行过程中的错误。如果有报错,async函数直接是reject状态。

2、判断info中的done值,是否为true,为true就代表迭代器已经执行完毕了,可以将value值resolve出去。反之,则继续调用_next将值传递到下一个去。

这里我唯一没有看明白的是`_throw`,这个看代码像是执行不到的。promise.resolve状态值应该是fulfilled。看懂的
可以在评论中和我说一下,感谢。

async/await的优势

每当一种新的语法糖出现,必定是弥补上一代解决方案的缺陷。

ex:

promise的出现,是为了去避免callback hell,避免的方式就是链式调用。

那async/await为了去解决什么呢?


用async/await去替换掉promise的几点必要性

同步的方式处理异步

async/await更贴近于同步性的风格,而promise则是用then的方式,于async/await相比,代码会变多,而且async/await和同步函数差别不大,promise则写法上还是有差距的。

promise和async/await代码对比

promise版

function getData() {
    getRes().then((res) => {
        console.log(res);
    })
}

async/await版

const getData = async function() {
    const res = await getRes();
    console.log(res);
}

中间值

用promise的时候会发现,多个promise串行的时候,后面的promise需要去获取前面promise的值是非常困难的。而async恰好解决了这个点。

promise获取中间值的例子

const morePromise = () => {
	return promiseFun1().then((value1) => {
		return promiseFun2(value1).then((value2) => {
			return promiseFun3(value1, value2).then((res) => {
				console.log(res);
			})
		}) 
	})
}

上面是嵌套版本的,可能根据不同的需求可以不嵌套的。

const morePromise = () => {
	return promiseFun1().then((value1) => {
		return promiseAll([value1, promiseFun2(value1)])
	}).then(([value1, value2]) => {
		return promiseFun3(value1, value2).then((res) => {
			console.log(res);
		})
	})
}

少了嵌套层级,但是还是不尽如人意。

用async/await优化例子

const morePromise = async function() {
	const value1 = await promiseFun1();
	const value2 = await promiseFun2(value1);
	const res = await promiseFun3(value1, valuw2);
	return res;
}

串行的异步流程,必定会有中间值的牵扯,所以async/await的优势就很明显了。

条件语句的情况

比如,目前有个需求,你请求完一个数据之后,再去判断是否还需要请求更多数据。用promise去实现还是会出现嵌套层级。

const a = () => {
    return getResult().then((data) => {
        if(data.hasMore) {
            return getMoreRes(data).then((dataMore) => {
                return dataMore;
            })
        } else {
            return data;
        }
    })
}

但是用async去优化这个例子的话,能使代码更加优美。

async/await优化例子

const a = async() => {
    const data = await getResult();
    if(data.hasMore) {
        const dataMore = await getMoreRes(data);
        return dataMore;
    } else {
        return data;
    }
}

async/await的劣势

上面我们讲了几点async/await的优势所在,但是async/await也不是万能的。上面清一色的是讲串联异步的场景。当我们变成并联异步场景时。还是需要借助于promise.all来实现

并联异步的场景

const a = async function() {
    const res = await Promise.all[getRes1(), getRes2()];
    return res;
}

async/await的错误处理

async/await在错误捕获方面主要使用的是try-catch。

try-catch

const a = async () => {
    try{
        const res = await Promise.reject(1);
    } catch(err) {
        console.log(err);
    }
}

promise的catch

可以抽离一个公共函数来做这件事情。因为每个promise后面都去做catch的处理,代码会写的很冗长。

const a = async function() {
    const res = await Promise.reject(1).catch((err) => {
        console.log(err);
    })
}
// 公共函数

function errWrap(promise) {
    return promise().then((data) => {
        return [null, data];
    }).catch((err) => {
        return [err, null];
    })
}

以上就是async/await的来龙去脉的详细内容,更多请关注亿速云其它相关文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI