异步编程小结
栏目: JavaScript · 发布时间: 6年前
内容简介:在javascript单线程的世界里,没有异步寸步难行。本章节介绍异步编程的发展,从在(javascript)单线程的世界里,如果有多个任务,就必须排队,前面一个完成,再继续后面的任务。就像一个ATM排队取钱似的,前面一个不取完,就不让后面的取。 为了这个问题,javascript提供了2种方式: 同步和异步。 异步就像银行取钱填了单子约了号,等着叫到号,再去做取钱,等待的时间里还可以干点其他的事儿~举个例子:通过api拿到数据,数据里面有图片,图片加载成功渲染,那么代码如下:
在javascript单线程的世界里,没有异步寸步难行。本章节介绍异步编程的发展,从 callback , Events 到 promise , generator , async/await .
为什么要使用异步编程
在(javascript)单线程的世界里,如果有多个任务,就必须排队,前面一个完成,再继续后面的任务。就像一个ATM排队取钱似的,前面一个不取完,就不让后面的取。 为了这个问题,javascript提供了2种方式: 同步和异步。 异步就像银行取钱填了单子约了号,等着叫到号,再去做取钱,等待的时间里还可以干点其他的事儿~
异步回调带来的问题
回调地狱 (Callbacks Hell)
举个例子:通过api拿到数据,数据里面有图片,图片加载成功渲染,那么代码如下:
// 伪代码
request(url, (data) => {
if(data){
loadImg(data.src, () => {
render();
})
}
})
复制代码
如果有在业务逻辑比较复杂或者NodeJS I/O操作比较频繁的时候,就成了下面这个样子:
doSth1((...args, callback) => {
doSth2((...args, callback) => {
doSth3((...args, callback) => {
doSth4((...args, callback) => {
doSth5((...args, callback) => {
})
})
})
})
})
复制代码
这样的 维护性 和 可读性 ,整个人瞬间感觉不好了~
异常处理
try {
setTimeout(() => {
throw new Error('unexpected error');
}, 100);
} catch (e) {
console.log('error2', e.message);
}
复制代码
以上代码运行抛出异常,但try catch不能得到未来时间段的异常。
流程控制不方便
流程控制只能通过维护各种 状态 来处理,不利于管理
异步编程现有解决方案对比
事件机制
不管浏览器还是NodeJS,提供了大量内置事件API来处理异步。
事件监听
浏览器中如: websocket , ajax , canvas , img , FileReader 等 NodeJS如: stream , http 等
自定义事件(本质上是一种发布订阅模式)
- NodeJS中的
EventEmitter事件模型 - 浏览器中:如DOM可使用
addEventListener,此外浏览器也提供一些自定义事件的API,但兼容性不好,具体可以这篇文章;也可以用Node中的EventEmitter;jquery中也对此做了封装,on,bind等方法支持自定义事件。
事件小结
事件一定程度上解决了 解耦 和提升了代码 可维护性 ;对于 异常处理 ,只有部分支持类似 error事件 才能处理。若想实现异常处理机制,只有自己模拟error事件,比较繁琐。
Promise
Promise严格来说不是一种新技术,它只是一种机制,一种代码结构和流程,用于管理异步回调。为了统一规范产生一个Promise/A+规范,点击查看Promise/A+中文版,cnode的 William17 实现了Promise/A+规范,有兴趣的可以点这里查看
-
promise状态由内部控制,外部不可变 - 状态只能从
pending到resovled,rejected,一旦进行完成不可逆 - 每次
then/catch操作返回一个promise实例,可以进行链式操作
部分代码如下:
readFile(path1).then(function (data) {
console.log(data.toString());
return readFile(path2);
}).then(function (data) {
console.log(data.toString());
return readFile(errorPath);
}).then(function (data) {
console.log(data.toString());
}).catch(function (e) {
console.log('error', e);
return readFile(path1);
}).then(function (data) {
console.log(data.toString());
});
复制代码
Promise的缺陷:
promise.catch
Generator
generator介绍
Generator是ES6提供的方法,是生成器,最大的特点:可以暂停执行和恢复执行(可以交出函数的执行权),返回的是 指针对象 .
- 需要自执行函数才能持续运行,否则需要手工调用流程
- 自执行函数借助promise, 获取异常和最终结果
generator 和 promise自执行实现
const run = function (generator) {
var g = generator()
var perform = function (result) {
if (result.done === true) {
return result.value
}
if (isPromise(result.value)) {
return result.value.then(function (v) {
return perform(g.next(v))
}).catch(function (e) {
return perform(g.throw(e))
})
} else {
return perform(g.next(result.value))
}
}
return perform(g.next())
}
const isPromise = f => f.constructor === Promise
function* g() {
var a = yield sleep(1000, _ => 1)
var b = yield sleep(1000, _ => 2)
return a + b
}
function sleep(d, fn) {
return new Promise((resolve, reject) => {
setTimeout(_ => resolve(fn()), d)
})
}
复制代码
由于以上问题,于是一个叫 co 库诞生,支持 thunk 和 Promise . 关于thunk可以查看 阮一峰老师的thunk介绍和应用
Async/Await
ES7提供了 async 函数,使得异步操作变得更加方便。
- 内置执行器
- 更好的语义
- 更多的实用场景,co参数Generator函数中
yield只能是promise和thunk
实例代码:
async function asyncReadFile() {
var p1 = readFile(path.join(__dirname, '../data/file1.txt'));
var p2 = readFile(path.join(__dirname, '../data/file2.txt'));
var [f1, f2] = await Promise.all([p1, p2]);
return `${f1.toString()}\n${f2.toString()}`;
}
(async function () {
try {
console.log(await asyncReadFile());
} catch (e) {
console.log(e.message)
}
})();
复制代码
Node8 async/await 支持
Node8.0 发布,全面支持 async/await , 推荐使用 async/await , 低版本node可以使用 babel 来编译处理。 而 为了方便 接口设计时 返回 promise 更方面使用者. 当然依然使用 callback , 通过 promisify 做转换, Node8.0 已经内置 util.promisify 方法。
参考资料
小结
异步编程 在javascript中扮演者重要的角色,虽然现在需要通过 babel , typescript 等编译或转换代码,跟着 规范 和 标准 走,就没有跑偏。
好久之前在github博客上的文章了。
如需转载,请备注出处。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Automate This
Christopher Steiner / Portfolio / 2013-8-9 / USD 25.95
"The rousing story of the last gasp of human agency and how today's best and brightest minds are endeavoring to put an end to it." It used to be that to diagnose an illness, interpret legal docume......一起来看看 《Automate This》 这本书的介绍吧!