开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第11天,点击查看活动详情
回调地狱时代
在ajax流行的时期,想必大家都知道一个ajax请求里边,在嵌套另外一个ajax请求。
function getList() {
// ...
var XHR = new XMLHttpRequest();
XHR.open('GET', url, true);
XHR.send();
XHR.onreadystatechange = function() {
if (XHR.readyState == 4 && XHR.status == 200) {
result = XHR.response;
console.log(result);// 拿到了结果
// 现在在发一个请求
}
}
}
这只是简单的发请求获取数据,还没有加上业务逻辑在里边,可以想想如果再把业务逻辑放在里边,后期的维护成本就高的不行了。
一个函数做一件事情
那就把复杂的逻辑,都单另出来,封装自己的业务逻辑。
// 一个简单的封装
function want() {
console.log('这是你想要执行的代码');
}
function fn(want) {
console.log('这里表示执行了一大堆各种代码');
// 其他代码执行完毕,最后执行回调函数
want && want();
}
fn(want);
但还是解决不了我们回调地狱的问题。只不过是看起来清晰了。
Promise登场
三种状态
- pending: 等待中,或者进行中,表示还没有得到结果
- resolved(Fulfilled): 已经完成,表示得到了我们想要的结果,可以继续往下执行
- rejected: 也表示得到结果,但是由于结果并非我们所愿,因此拒绝执行
new Promise(function(resolve, reject) {
if(true) { resolve() };
if(false) { reject() };
})
then方法
接收两个参数,一个是成功的回调,一个是失败的回调
function fn(num) {
return new Promise(function(resolve, reject) {
if (typeof num == 'number') {
resolve();
} else {
reject();
}
}).then(function() {
console.log('参数是一个number值');
}, function() {
console.log('参数不是一个number值');
})
}
fn('hahha');
fn(1234);
Promise.all
将多个 Promise 实例,包装成一个新的 Promise 实例
const p = Promise.all([p1, p2, p3]);
p的状态由p1、p2、p3决定,分成两种情况。
- (1)只有
p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。 - (2)只要
p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
aysnc/await
Generator 函数的语法糖
const asyncReadFile = async function () {
const f1 = await readFile('/etc/fstab');
const f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
总结
回调地狱的出现,让人头疼,不好维护。紧接着出现了Promise,使用链式调用的方式,解决了回调地狱的问题;同时还有一个就是满屏的then操作,不好看;紧接着出现了async/await。他们是Gennerator的语法糖。将异步的函数整成了同步的写法。让人一幕了然。