写在前面, 这个话题其实还挺大的, 我本身恐怕力有不逮, 因此只能算是笔记总结, 写的确定会有点简略. 有错误实在太正常了. 但愿能多多指教.python
这篇文章仅仅是解释一下现有的异步编程方案不涉及具体原理, 可是个人想法是试试看能不能每一个方案都本身实现一遍, 因此多是系列文章也可能就此太监了.web
想必你们都看过上面的图片, 虽然不是js代码, 甚至不是回调, 可是各位同窗估计对callback hell感同身受. 可是事实上回调函数跟异步编程并无必然的联系. 回调只是一种设计模式. 同步代码一样能够使用回调只是大部分时候会让人以为画蛇添足而已.ajax
你们都知道回调并非那么优雅, 不少时候代码可能写成这样:编程
asyncJob1(function () {
asyncJob2(function () {
asyncJob3(function () {
// your code
})
})
})
复制代码
虽然问题算是解决了吧, 可是代码看着真是使人头痛. 玩意逻辑稍微复杂一点说不定真会出现下面的状况: c#
大概美军也是回调写多了吧2333.设计模式
大部分gui程序都是采用事件驱动, web固然也不例外, 最典型的就是dom事件:promise
div.on('click', function () {
// balabala
})
复制代码
这个几乎都是跟回调和事件循环相关的, 后面会详细讲到的.dom
根据promise/A+的规范:koa
一个Promise必须处在其中之一的状态:pending, fulfilled 或 rejected. 若是是pending状态,则promise能够转换到fulfilled或rejected状态。 若是是fulfilled状态,则promise不能转换成任何其它状态。 若是是rejected状态,则promise不能转换成任何其它状态。异步
Promise都会有个then方法, 制定了fulfilled和rejected两种请况的回调, 同时then会返回一个Promise对象, 这就容许咱们链式调用了:
ajax('xxx').then(res => res).then(res => res)
复制代码
虽然Promise的方案比回调已经好太多了. 可是不难发现多个then其实未必比回调好看太多, 只能说把回调铺平了. 可能Promise并非最优雅的解决方案.
generator在各个语言里都有出现, python,c#等, 这里不说概念, 只说在js里该怎么使用就行, 基本理解就是generator是拥有多个返回值的函数, 每次调用next就会调用一次返回. 这就是所谓 控制权移交, 固然这样不足以体现其优越性, generator最重要的特性就是分步数据传递: next的参数能够做为上次yield的返回值, 其实直觉上不是很能理解, 不过咱们这里只要知道有这么个东西就成, 下面是代码示例:
var f = function* (x) {
var y = yield x + 1
yield y + 1
return y
}
var t = f(1)
var s = t.next()
console.log(s) // 2
var p = t.next(4) // 这里的4做为上次yield的返回值
console.log(p) // 5
复制代码
有这么一个特性, 那么下面的操做性就很强了, 好比tj的著名的co:
co(function* () {
var result = yield Promise.resolve(true);
return result;
}).then(function (value) {
console.log(value);
}, function (err) {
console.error(err.stack);
});
复制代码
能够说写法已经很同步了. 固然这个也不是最终的解决方案, 否则为何koa2要用async/await呢hhh
一样对于async/await 咱们先不纠结其原理, 咱们只须要知道它是generator和promise两者结合起来的语法糖(不过也真够甜的)
每一个async必然返回一个Promise对象, 因此async会像瘟疫一个把你的每一个函数都变成async函数, 所谓能够async的终将async, 下面是例子:
// Promise的解决方案
function foo () {
return ajax('xxx').then(res => res).then(res => res)
}
async function bar () {
try {
const response = await ajax('xxx')
console.log(response)
} catch (e) {
throw e
}
}
复制代码
是否是优雅了太多, 除了一大片async/await, 不过也算小小的代价.
利用午休时间码了出来, 不知道有多少错误呢hhh