"小和山的菜鸟们",为前端开发者提供技术相关资讯以及系列基础文章。为更好的用户体验,请您移至我们官网小和山的菜鸟们 ( https://xhs-rookies.com/ ) 进行学习,及时获取最新文章。
在 MDN 的 JavaScript 系列中我们已经学习了 callback、promise、generator、async/await。而在这一篇文章中,作者将以实际样例阐述异步发展历史,介绍每种实现方式的优势与不足,以期帮助读者熟悉历史进程并把握异步发展的脉络。
几十年前的导航网站,清爽又简单,没有什么特别的功能,只是单纯的展示,现成的网页在服务器上静静躺着,高效毫无压力,让人很喜欢。
几十年后的今天,静态页面远不能满足用户的需求,网站变得复杂起来,用户交互越来越频繁,从而产生大量复杂的内部交互,为了解决这种复杂,出现了各种系统“模式”,从而很容易的在外部获取数据,并实时展示给用户。
获取外部数据实际上就是“网络调用”,这个时候“异步”这个词汇出现了。
异步指两个或两个以上的对象或事件不同时存在或发生(或多个相关事物的发生无需等待其前一事物的完成)
异步 callbacks其实就是函数,只不过是作为参数传递给那些在后台执行的其他函数。当那些后台运行的代码结束,就调用 callbacks 函数,通知你工作已经完成,或者其他有趣的事情发生了。
场景
let readFile = (path, callBack) => {
setTimeout(function () {
callBack(path)
}, 1000)
}
readFile('first', function () {
console.log('first readFile success')
readFile('second', function () {
console.log('second readFile success')
readFile('third', function () {
console.log('third readFile success')
readFile('fourth', function () {
console.log('fourth readFile success')
readFile('fifth', function () {
console.log('fifth readFile success')
})
})
})
})
})
优点:
缺点:
一个Promise对象代表一个在这个 promise 被创建出来时不一定已知的值。它让您能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。 这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise,以便在未来某个时候把值交给使用者。
场景
let readFile = (path) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (!path) {
reject('error!!!')
} else {
console.log(path + ' readFile success')
resolve()
}
}, 1000)
})
}
readFile('first')
.then(() => readFile('second'))
.then(() => readFile('third'))
.then(() => readFile('fourth'))
.then(() => readFile('fifth'))
优点:
缺点:
Generator函数是 ES6 中提供的一种异步编程解决方案。语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态,需要使用next()函数来继续执行下面的代码。
特征
场景
var readFile = function (name, ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(name + '读完了')
resolve()
}, ms)
})
}
var gen = function* () {
console.log('指定generator')
yield readFile('first', 1000)
yield readFile('second', 2000)
yield readFile('third', 3000)
yield readFile('forth', 4000)
yield readFile('fifth', 5000)
return '完成了'
}
var g = gen()
var result = g.next()
result.value
.then(() => {
g.next()
})
.then(() => {
g.next()
})
.then(() => {
g.next()
})
.then(() => {
g.next()
})
优点:
缺点:
async functions 和 await 关键字是最近添加到 JavaScript 语言里面的。它们是 ECMAScript 2017 JavaScript 版的一部分(参见ECMAScript Next support in Mozilla)。简单来说,它们是基于 promises 的语法糖,使异步代码更易于编写和阅读。通过使用它们,异步代码看起来更像是老式同步代码,因此它们非常值得学习。
场景 1
var readFile = function (name, ms) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(name + '读完了')
resolve()
}, ms)
})
}
async function useAsyncAwait() {
await readFile('first', 1000)
await readFile('second', 2000)
await readFile('third', 3000)
await readFile('forth', 4000)
await readFile('fifth', 5000)
console.log('async文件阅读完毕')
}
useAsyncAwait()
优点
语义更清晰、简洁
缺点
场景 2 场景 1 中的代码,其实 second,third 的伪请求其实并不依赖于 first,second 的结果,但它们必须等待前一个的完成才能继续,而我们想要的是它们同时进行,所以正确的操作应该是这样的。
async function useAsyncAwait() {
const first = readFile('first', 1000)
const second = readFile('second', 2000)
const third = readFile('third', 3000)
const forth = readFile('forth', 4000)
const fifth = readFile('fifth', 5000)
console.log('async文件阅读完毕')
await first
await second
await third
await forth
await fifth
}
useAsyncAwait()
在这里,我们将三个 promise 对象存储在变量中,这样可以同时启动它们关联的进程。
在这篇文章中,我们已经介绍了 JavaScript 异步发展史中 --- callback、promise、generator、async/await 的使用方式、优点与缺点。
发展史 | 优点 | 缺点 |
---|---|---|
callback | 解决了同步问题 | 回调地狱、可读性差、无法 try / catch 、无法 return |
promise | 一定程度上解决了回调地狱的可读性 | 无法取消、任务多时,同样存在语义不清晰 |
generator | 可以控制函数的执行,可以配合 co 函数库使用 | 流程管理却不方便(即何时执行第一阶段、何时执行第二阶段 |
async/await | 语义更清晰、简洁,内置执行器 | 认知不清晰可能会造成大量 await 阻塞(程序并不会等在原地,而是继续事件循环,等到响应后继续往下走)情况 |
而在现有的异步解决方案中,async/await 是使用人数最多的,它带给我们最大的好处即同步代码的风格,语义简洁、清晰。
如下图,最近项目中需要这么个树形结构可视化数据图形,找了好多可视化插件,没...
背景 做过前端开发都知道前端的工作内容是很多的,对于HTML、CSS、Javascript、I...
近年来,出国留学成为了越来越多国内学生的选择,掀起了一股“留学热”,而英语...
前言 在上一篇文章中我为大家介绍了Simpe项目的一些 背景知识 以及如何使用 有限...
最近这个 Apache Pulsar 消息中间件非常的火,号称下一代消息中件,今天,就一起...
TOP云 (west.cn)4月24日消息,昨天上午 域名 中介平台Buckley Media Group知名...
HTML+CSS 1.对WEB标准以及W3C的理解与认识 标签闭合、标签小写、不乱嵌套、提高...
yii-log-target - 监控系统异常且多渠道发送异常信息通知(Bark、Chanify、钉钉群...
src和href之间存在区别,能混淆使用。src用于替换当前元素,href用于在当前文档...
今天安装了IE8,去 微软网站下载 的时候发现已经提供中文版的beta了,哈哈 发现I...