Promise基本使用
一、异步编程
目前最常见的异步就是定时器
setTimeout(()=>{
console.log('定时器');
},2000)
之前的很长一段时间要想实现异步,通常是通过回调函数的形式来实现,但这有一个很明显的问题,容易出现回调地狱。
举个例子,如果我想在控制台输出十次"回调地狱",但是每一次输入下一句话之前都延迟两秒。代码如下:
setTimeout(() => {
console.log('回调地狱1');
setTimeout(() => {
console.log('回调地狱2');
setTimeout(() => {
console.log('回调地狱3');
setTimeout(() => {
console.log('回调地狱4');
setTimeout(() => {
console.log('回调地狱5');
setTimeout(() => {
console.log('回调地狱6');
setTimeout(() => {
console.log('回调地狱7');
setTimeout(() => {
console.log('回调地狱8');
setTimeout(() => {
console.log('回调地狱9');
setTimeout(() => {
console.log('回调地狱10');
},2000)
},2000)
},2000)
},2000)
},2000)
},2000)
},2000)
},2000)
},2000)
}, 2000);
这段代码就功能来说是完全没问题的,但是不难发现嵌套越深代码编写难度就越高,可读性就越低,这种情况我们就称之为回调地狱。
一、Promise实现异步
Promise是ES6引入的用于解决异步问题的函数,可以封装异步的任务,并对结果进行处理。它最大的好处就是可以解决回调地狱的问题,在现在的开发项目当中用的频率都非常的高。
步骤:
Promise:启动异步任务=>返回promise对象=>给promise对象绑定回调函数(支持链式调用)
1.生成promise实例对象
const pro=new Promise((resolve, reject) => {
//异步操作步骤
//异步完成后,调用resolve或reject方法
})
// resolve 解决 函数类型的数据
// reject 拒绝 函数类型的数据
当异步操作成功时,调用resolve,操作失败调用reject。
2.promise实力对象有三种状态
pending:进行中,表示还没有得到结果。
fulfilled:已成功,表示异步操作完成,已经得到正确结果。
rejected:已失败,表示异步操作完成,但未得到正确的结果。
promise的状态可以通过调用resolve或者reject函数从进行中变成已成功或者已失败。
3.promise实例对象的then方法
pro.then(()=>{},()=>{});
promise实例对象有一个then方法,它带有两个函数类型参数,当promise对象状态为fulfilled时,会执行then方法的参数的第一个函数;当promise对象状态为rejected时,会执行then方法的参数的第二个函数。
4. 显示成功或失败的原因
无论成功或失败,均可以通过resolve方法或者reject方法的参数,向then方法传递数据。
new Promise((resolve, reject) => {
//异步操作步骤
//异步完成后
resolve("resolve")
//或
reject("reject")
}).then((value)=>{
console.log(value); //resolve
},(reson)=>{
console.log(reson) //reject
})
5.链式调用
在promise实例对象后面直接.then方法,每调用一次then方法都会反回一个新的promise对象,新对象的状态默认是成功的。
当第一次调用的是resolve方法时:
new Promise((resolve, reject) => {
setTimeout(()=>{
console.log("promise");
resolve()
},2000)
}).then(
()=>{console.log("返回的第一个成功promise");},
()=>{console.log("返回的第一个失败promise");}
).then(
()=>{console.log("返回的第二个成功promise");},
()=>{console.log("返回的第二个失败promise");}
)
//promise
//返回的第一个成功promise
//返回的第二个成功promise
当第一次调用的是reject方法时:
new Promise((resolve, reject) => {
setTimeout(()=>{
console.log("promise");
reject()
},2000)
}).then(
()=>{console.log("返回的第一个成功promise");},
()=>{console.log("返回的第一个失败promise");}
//这里会默认返回一个成功的promise
).then(
()=>{console.log("返回的第二个成功promise");},
()=>{console.log("返回的第二个失败promise");}
)
// promise
// 返回的第一个失败promise
// 返回的第二个成功promise
6.自定义返回值
then方法中也可以自定义返回值。
- 自定义返回的promise
new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise");
resolve()
}, 2000)
}).then(
() => {
console.log("返回一个失败的promise");
return new Promise((resolve, reject) => {
reject();
})
}).then(
() => { console.log("返回的第二个成功promise"); },
() => { console.log("返回的第二个失败promise"); }
)
//promise
//返回一个失败的promise
//返回的第二个失败promise
- 自定义返回任意值
new Promise((resolve, reject) => {
setTimeout(() => {
console.log("promise");
resolve()
}, 2000)
}).then(
() => {
return 111
}).then(
(data) => { console.log(data); }
)
// promise
// 返回111
// 111
7.使用链式调用来改写文档开头的例子,可以方便我们解决回调地狱的问题。
let output = function (time) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve()
}, time)
})
}
output(2000).then(() => {
console.log('回调地狱1');
//自定义返回值
return output(2000)
}).then(() => {
console.log('回调地狱2');
return output(2000)
}).then(() => {
console.log('回调地狱3');
return output(2000)
}).then(() => {
console.log('回调地狱4');
return output(2000)
}).then(() => {
console.log('回调地狱5');
return output(2000)
}).then(() => {
console.log('回调地狱6');
return output(2000)
}).then(() => {
console.log('回调地狱7');
return output(2000)
}).then(() => {
console.log('回调地狱8');
return output(2000)
}).then(() => {
console.log('回调地狱9');
return output(2000)
}).then(() => {
console.log('回调地狱10');
return output(2000)
})