阅读本篇文章大约需要7分钟,如果你有充足的时间,可以跳至文末参考文章细品;如果你时间紧迫可以直接到三、async和await一节。
js是单线程依赖异步处理机制的一门语言,今天就来说一说js异步处理从回调函数到Promise到async await的发展。
以下的代码异步操作都以setTimeout为例:
一、回调函数
异步处理机制就是阻塞的任务就先跳过,等到阻塞结束在回调返回里再执行。如下代码:
console.log(1)
setTimeout(() => {
console.log(2) // 阻塞1秒
}, 1000)
console.log(3)
没有异步处理的同步语言的话会等待阻塞,拿上面的代码来说就是先输出个1,然后等啊等输出2,最后输出3。但是js的异步处理机制不酱紫,它会按1>3>2的顺序输出,它不等待阻塞,像风不等跟不上的沙。上面的箭头函数就是一个回调,算是最早的js对异步的处理,但是如果很多异步嵌套的话就有很多的回调,地狱级的回调非常不利于代码直观的阅读。
二、Promise
随着js的发展,es6提供了Promise对象相比于回调函数方便了那么一些些,避免出现了地狱回调的写法,相比回调代码读起来也趋于同步。如下代码:
var testPromise = new Promise((resolve, reject) => {
setTimeout(function() {
resolve(1) // 返回到then
}, 1000)
reject(a)
})
// 避免了嵌套增强代码可读性, 注:下面的结果和错误不是同时得到,注释掉上面没有定义的a行会走then;放出来会走catch
testPromise.then(response => {
console.log(response) // 等待1s得到结果: 1
}).catch(err => {
console.error(11, err) // 得到错误: a is not defined
})
// 下面代码会优先执行
console.log(0)
以上代码打印结果为:0 -> 1或者是0->11,报错信息
三、async和await
随着es6的发展,到了es7的时候出现了async和await,async就是告诉程序我这个函数里有异步,await就是告诉程序要等我后面紧跟的异步执行代码有了结果之后才能往下走,出了async就不等了。如下代码:
async function testAsync() {
console.log(1)
// 等待一秒执行,await就是历史中的回调啦
response = await new Promise(resolve => {
setTimeout(() => {
resolve(3)
}, 1000)
})
// 排排队,await后的代码执行结束之后排到下面代码
console.log(response)
console.log(4)
}
testAsync()
// 外面的代码不排排队,依然是异步的
console.log(2)
以上代码打印的顺序为:1 -> 2 -> 3 -> 4
四、结合try catch进阶处理
在实际项目中,可以加上try catch以优化代码的处理使代码强壮似男友,如下代码:
// 封装的请求
function get (method, url, params) {
return new Promise(resolve => {
// ajax/fetch/axios或者微信小程序的wx.request/uni-app的uni.request,请求方式具体看实际项目
...
})
}
// 页面中请求接口调用
async function getList() {
try {
const response = await get('POST', 'api/list', { keyword: '' })
// 根据服务端定义的报错code抛出报错信息到catch
if (response.code !== 200) throw (response.message)
// 下面做接口正常返回数据的处理,比如:
const list = response.data.list
...
} catch (error) {
console.error(error)
}
}
getList()
总结,时代在发展,我们要进步,异步机制到async await这一步已经在代码思路上趋于同步了,只是实际内部的执行顺序还是异步。让我们的代码明显更加易读了,希望本文对你有些许帮助哟,动动手指点个赞吧,你的鼓励是我创作的动力,笔芯。