We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
在javascript单线程的世界里,没有异步寸步难行。本章节介绍异步编程的发展,从callback,Events到promise,generator,async/await.
callback
Events
promise
generator
async/await
在(javascript)单线程的世界里,如果有多个任务,就必须排队,前面一个完成,再继续后面的任务。就像一个ATM排队取钱似的,前面一个不取完,就不让后面的取。 为了这个问题,javascript提供了2种方式: 同步和异步。 异步就像银行取钱填了单子约了号,等着叫到号,再去做取钱,等待的时间里还可以干点其他的事儿~
举个例子:通过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等
websocket
ajax
canvas
img
FileReader
stream
http
EventEmitter
addEventListener
jquery
on
bind
事件一定程度上解决了解耦和提升了代码可维护性;对于异常处理,只有部分支持类似error事件才能处理。若想实现异常处理机制,只有自己模拟error事件,比较繁琐。
解耦
可维护性
异常处理
error事件
Promise严格来说不是一种新技术,它只是一种机制,一种代码结构和流程,用于管理异步回调。为了统一规范产生一个Promise/A+规范,点击查看Promise/A+中文版,cnode的William17实现了Promise/A+规范,有兴趣的可以点这里查看
William17
pending
resovled
rejected
then/catch
部分代码如下:
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是ES6提供的方法,是生成器,最大的特点:可以暂停执行和恢复执行(可以交出函数的执行权),返回的是指针对象.
指针对象
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介绍和应用
thunk
Promise
ES7提供了async函数,使得异步操作变得更加方便。
async
yield
实例代码:
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.0发布,全面支持 async/await, 推荐使用 async/await, 低版本node可以使用 babel来编译处理。 而 为了方便 接口设计时 返回 promise 更方面使用者. 当然依然使用 callback , 通过 promisify做转换, Node8.0已经内置 util.promisify方法。
Node8.0
babel
promisify
util.promisify
异步编程在javascript中扮演者重要的角色,虽然现在需要通过babel,typescript等编译或转换代码,跟着规范和标准走,就没有跑偏。
异步编程
typescript
规范
标准
如需转载,请备注出处。
The text was updated successfully, but these errors were encountered:
No branches or pull requests
在javascript单线程的世界里,没有异步寸步难行。本章节介绍异步编程的发展,从
callback
,Events
到promise
,generator
,async/await
.为什么要使用异步编程
在(javascript)单线程的世界里,如果有多个任务,就必须排队,前面一个完成,再继续后面的任务。就像一个ATM排队取钱似的,前面一个不取完,就不让后面的取。
为了这个问题,javascript提供了2种方式: 同步和异步。
异步就像银行取钱填了单子约了号,等着叫到号,再去做取钱,等待的时间里还可以干点其他的事儿~
异步回调带来的问题
回调地狱 (Callbacks Hell)
举个例子:通过api拿到数据,数据里面有图片,图片加载成功渲染,那么代码如下:
如果有在业务逻辑比较复杂或者NodeJS I/O操作比较频繁的时候,就成了下面这个样子:
这样的
维护性
和可读性
,整个人瞬间感觉不好了~异常处理
以上代码运行抛出异常,但try catch不能得到未来时间段的异常。
流程控制不方便
流程控制只能通过维护各种
状态
来处理,不利于管理异步编程现有解决方案对比
事件机制
不管浏览器还是NodeJS,提供了大量内置事件API来处理异步。
事件监听
浏览器中如:
websocket
,ajax
,canvas
,img
,FileReader
等NodeJS如:
stream
,http
等自定义事件(本质上是一种发布订阅模式)
EventEmitter
事件模型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实例,可以进行链式操作部分代码如下:
Promise的缺陷:
promise.catch
才能才能接收到Generator
generator介绍
Generator是ES6提供的方法,是生成器,最大的特点:可以暂停执行和恢复执行(可以交出函数的执行权),返回的是
指针对象
.generator 和 promise自执行实现
由于以上问题,于是一个叫 co库诞生,支持
thunk
和Promise
.关于thunk可以查看阮一峰老师的thunk介绍和应用
Async/Await
ES7提供了
async
函数,使得异步操作变得更加方便。yield
只能是promise
和thunk
实例代码:
Node8 async/await 支持
Node8.0
发布,全面支持async/await
, 推荐使用async/await
, 低版本node可以使用babel
来编译处理。 而 为了方便 接口设计时 返回promise
更方面使用者. 当然依然使用callback
, 通过promisify
做转换,Node8.0
已经内置util.promisify
方法。参考资料
小结
异步编程
在javascript中扮演者重要的角色,虽然现在需要通过babel
,typescript
等编译或转换代码,跟着规范
和标准
走,就没有跑偏。如需转载,请备注出处。
The text was updated successfully, but these errors were encountered: