1、回调函数(callback)
setTimeout(() => {
// callback 函数体
}, 1000)
优点:解决同步问题
缺点:(1)耦合性强,维护性差
//回归地狱
ajax('XXX1', () => {
// callback 函数体
ajax('XXX2', () => {
// callback 函数体
ajax('XXX3', () => {
// callback 函数体
})
})
})
2、Promise
状态:pending(进行中)、fulfilled(已成功)和rejected(已失败);
特点:
(1)通过then实现链式操作(微任务),返回promise对象;
(2)如果我们在 then 中 return ,return 的结果会被 Promise.resolve() 包装
优点:解决回归地狱
(3)Promise.prototype.catch() 捕捉错误
缺点:无法取消promise,过程不可逆
//下面是一个用Promise对象实现的 Ajax 操作的例子
/*
是对 XMLHttpRequest 对象的封装,
用于发出一个针对 JSON 数据的 HTTP 请求,
并且返回一个Promise对象
*/
const ajax = fucntion(url) {
const promise = new Promise((resolve,reject) =>{
const handler = function() {
if(this.readyState ! ==4) {
return;
}
if(this.status === 200) {
resolve(this.response);
}else {
reject(new Error(this.statusText));
}
};
const xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onreadystatechange = handler;
xhr.responseType = 'json';
xhr.setRequestHeader('Accept', 'application/json');
xhr.send();
});
return promise;
}
//使用ajhx
ajax('XXX1')
.then(res => {
// 操作逻辑
return ajax('XXX2')
}).then(res => {
// 操作逻辑
return ajax('XXX3')
}).then(res => {
// 操作逻辑
}).catch(error =>{
console.log('发生错误了')
})
3、Generator(语法糖,函数外面用*,内部异步用yield)
generator就是能够返回多次的“函数”?返回多次有啥用
(1)、调用generator对象有两个方法,一是不断地调用generator对象的next()方法:当执行到done为true时,value就是返回值
(2)第二个方法是直接用for ... of循环迭代generator对象,这种方式不需要我们自己判断done:
应用:
要编写一个产生斐波那契数列的函数
function* fn(){
yield fn1();
yield fn2();
}
let it = fn()
let res1 = it.next()
let res2 = it.next()
4、Async/ await
最终解决方案,代码结构清晰
(1)await 到底在等啥
一般来说,都认为 await 是在等待一个 async 函数完成。不过按语法说明,await 等待的是一个表达式,这个表达式的计算结果是 Promise 对象或者其它值(换句话说,就是没有特殊限定);
(2) async 函数返回一个 Promise 对象,await返回表达即计算的结果。
(3)使用规则
async function test() {
// 以下代码没有依赖性的话,完全可以使用 Promise.all 的方式
// 如果有依赖性的话,其实就是解决回调地狱的例子了
await fn1()
await fn2()
}
//栗子---注意看结果:输出了promise
说明:参考文章如下
1、阮一峰es6解说
2、JS异步解决方案的发展历程以及优缺点