- 回调函数(callback)
setTimeout(() => { // callback 函数体 }, 1000)
ajax('XXX1', () => { // callback 函数体 ajax('XXX2', () => { // callback 函数体 ajax('XXX3', () => { // callback 函数体 }) }) })
优点:
-
简单、容易理解
-
解决了同步的问题(只要有一个任务耗时很长,后面的任务都必须排队等着, 会拖延整个程序的执行。)
缺点:
-
易形成回调地狱
-
不能用try...catch捕获错误
-
不能return
-
不利于维护,代码耦合高
- 事件监听
var events = new Events(); events.addEvent('done', function(data1) { var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://www.apiopen.top/weatherApi?city=番禺'); xhr.send(); xhr.onreadystatechange = function() { if(this.readyState !== 4) return; if(this.status === 200) { data1 = JSON.parse(data1); var data2 = JSON.parse(this.response); console.log(data1, data2); } } }); var xhr = new XMLHttpRequest(); xhr.open('GET', 'https://www.apiopen.top/weatherApi?city=广州'); xhr.send(); xhr.onreadystatechange = function() { if(this.readyState !== 4) return; if(this.status === 200) { events.fireEvent('done', this.response); } };
优点:
1、与回调函数相比,事件监听方式实现了代码的解耦,将两个回调函数分离了开来, 更方便进行代码的管理。
2、容易理解,可以绑定多个事件,每个事件可以指定多个回调函数
缺点:
1、使用起来不方便,每次都要手动地绑定和触发事件
-
发布/订阅(观察者模式)
类似于事件监听,但是可以通过‘消息中心‘,知道现在有多少发布者,多少订阅者;
-
Promise
promise就是为了解决callback的问题而产生的。
Promise 实现了链式调用,也就是说每次 then 后返回的都是一个全新 Promise, 如果我们在 then 中 return ,return 的结果会被 Promise.resolve() 包装。
优点:
1、解决回调地狱问题
2、更好地进行错误捕获
缺点:
1、无法取消promise,一旦新建它就会立即执行,无法中途取消;
2、如果不设置回调函数,promise内部抛出的错误,不会反应到外部;
3、当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开 始还是即将完成)
- Generator
function *fetch() { yield ajax('XXX1', () => {}) yield ajax('XXX2', () => {}) yield ajax('XXX3', () => {}) } let it = fetch() let result1 = it.next() let result2 = it.next() let result3 = it.next()
优点:
generator 方式使得异步操作很接近同步操作,十分的简洁明了。另外,gen 执行 yield 语句时,只是将执行上下文暂时弹出,并不会销毁,这使得上下文状态被保存
缺点:
流程管理不方便,需要一个执行器来执行 generator 函数
-
Async/await
async、await 是异步的终极解决方案
优点:
1、最简洁,最符合语义,最接近同步代码,最适合处理多个 Promise 异步操作。
2、相比 generator 方式,async 方式省掉了自动执行器,减少了代码量
缺点:
await 将异步代码改造成同步代码,如果多个异步操作没有依赖性而使用 await 会导致性能上的降低。