如:当我们想每等2秒打印一次我是第几名时,按照正常的写法则会出现回调嵌套回调,当里面的需求太多则会形成回调地狱的问题。
setTimeout(() => {
console.log('我是第111111名');
setTimeout(() => {
console.log('我是第222222名');
setTimeout(() => {
console.log('我是第333333名');
}, 2000)
}, 2000)
}, 2000)
Promise的出现就是为了解决这种回调地狱的问题,有利于代码阅读
1,每个Promise实例都会有三种状态,pending(进行中) ,fulfillrd(成功),resject(已失败)。创建时默认状态为pending,只有异步操作的结果可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。一旦状态确定就不会再变了。Promise对象的改变只有两种可能:pending变为fulfillrd(成功),或pending变为resject(已失败)。
2,promis是一个构造函数可以创建promise实例:const p=new Promise( );new出来的promis 实例对象就代表一个异步操作。
3,于是可以用promise的链式调用的方法去解决,上面例子这种回调地狱的问题
new出来的Promise实例内有一个回调函数,可以封装异步操作。
回调函数有两个参数(resolve, resject),都是函数。如果异步执行成功会调用resolve()函数,并把成功返回的结果放入resolve中,通过.then的方法取出。
new Promise((resolve, resject) => {
setTimeout(() => {
resolve("我是第111111名");
}, 2000);
}).then((res) => {
console.log(result);
return new Promise((resolve, resject) => {
setTimeout(()=>{
resolve("我是第222223名");
},2000)
});
}).then((res)=>{
console.log(res);
return new Promise((resolve, resject) => {
setTimeout(()=>{
resolve("我是第333333名");
},2000)
});
}).then((res)=>{
console.log(res);
})
4,上面代码可以实现,但是看出频繁new Promise比较繁琐,而且promise所封装的异步的操作相同(都是每间隔2秒打印一个名次),于是可以给Promise封装为一个函数,直接调用函数封装异步操作。
//可以定义一个排名的函数ranking
function ranking(num) {
//每次调用ranking都返回一个Promise
return new Promise((resolve, resject) => {
//在peomise中封装好异步操作
//设置一个定时器,间隔2秒把成功的作为参数传递给resolve函数
setTimeout(() => {
resolve(num);
}, 2000);
});
}
//每次只需要调用函数就能直接完成异步的封装,通过.then获取异步结果
ranking("我是第一名")
.then((res) => {
console.log(res);
//继续返回新的promise,进行链式调用
return ranking("我是第二名");
})
.then((res) => {
console.log(res);
return ranking("我是第三名");
})
.then((res) => console.log(res));
5,promose的链式调用适用,下一步异步操作需要上一步异步的结果作为依赖的情况下使用。并发的情况用promise.all