promise的产生
回调地狱,又称恶魔金字塔,指的是回调函数层层嵌套的写法。这种写法往往让人难以理解,而且令代码不美观,所以称之为回调地狱
举一个简单的例子:
fn(function() {
console.log("第一个函数");
fn(function() {
console.log("第二个函数");
fn(function() {
console.log("第三个函数");
fn(function() {
console.log("第四个函数");
})
})
})
})
function fn(cb) {
cb();
}
而在ajax依赖调用时,也会出现这种情况,所以,promise便诞生了。
Promise对象
Promise是一种思维方式,是一种解决回调地狱的方案(Promise 是异步编程的一种解决方案)。
所谓的Promise,简单来说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
一、Promise的三种状态
- Pending(进行中)
实例化一个promise对象什么都不做
let p = new Promise(() => {
//这里是回调函数
})
console.log(p);
可看到PromiseState状态为“pendding”
PromiseResult为结果,此刻这个对象什么都没做,所以为undefined
- Resolved(已完成,又称Fulfilled)
resolve, reject :成功状态和失败状态,参数名字可自定义,但是顺序不可调换
调取resolve 状态会改变,“fulfilled” 状态(成功状态)
给resolve传参,结果[[PromiseResult]]得值就是传递的参数
//resolve, reject 成功状态和失败状态,参数名字可自定义,但是顺序不可调换
let p = new Promise((resolve, reject) => {
resolve('hello'); //调取resolve 状态会改变,"fulfilled" 状态(成功状态)
//给resolve传参,结果[[PromiseResult]]得值就是传递的参数
})
console.log(p);
- Rejected(已失败)
reject用法同resolve,不同的是调取reject会抛出异常
let p = new Promise((resolve, reject) => {
reject('error'); //reject "rejected"状态 并且抛出错误
//给reject传参,结果[[PromiseResult]]得值就是传递的参数
})
console.log(p);
*注:可以把Promise看成是状态机,当该Promise对象创建出来之后,其状态就是进行中,然后通过程序来控制到底是执行已完成,还是执行已失败。因为Promise处理的是异步任务,所以我们还得对Promise做监听,当Promise的状态发生变化时,我们要执行相应的函数。
then实际上就是对promise的状态监听
二、promise的then方法
每个promise对象都有then方法,then会有两种回调函数:1、onResolved 2、onReject
当promise对象状态为已完成时,触发第一个参数函数;当状态为已失败时,触发第二个参数函数(第二个参数函数,可写可不写)
每一个函数中的参数,指当初状态改变时,所保存的数据。
let p = new Promise((res, rej) => {
// res("succeed");
rej("unsuccessed");
})
p.then(function(res) { //这个位置接收的参数是PromiseResult的值
//onResolved:当Promise对象是一个fulfilled状态时执行
console.log("onResolved", res);
}, function(rej) {
//onReject:当Promise对象是一个rejected状态时执行
console.log("onReject", rej);
})
then的三种返回值
- 如果then的回调不返还任何内容,会返还一个结果为undefined的promise对象
let t = p.then(function(res) {
console.log("success", res);
})
console.log(t);
得到的结果:
返回了一个空的Promise对象
- 如果返还普通内容会把它包装成promise对象,并把返还的值作为结果值(PromiseResult的值)
let t = p.then(function(res) {
return 2222;
})
console.log(t);
返回一个结果为返回值的promise对象
- 如果返还一个promise对象,then会自动吧原来的promise对象返还
let t = p.then(function(res) {
return new Promise(resolve => {
resolve("返还的promise");
})
})
console.log(t);
自动返回原来的promise对象
由此我们可以得到:无论怎样,then都会返回一个promise对象,而所有的promise对象都有then方法,所以then方法可以无限调用。
利用then的链式调用解决回调地狱
改写开头回调地狱:
function fn() {
return new Promise((res, rej) => {
res("hello");
})//返回一个promise对象
}
fn().then(res => {
console.log("第一个函数");
return fn();
}).then(res => {
console.log("第二个函数");
return fn();
}).then(res => {
console.log("第三个函数");
return fn();
}).then(res => {
console.log("第四个函数");
console.log(res);
})
如此,代码就显得雅观很多
总结
综上所述,我们可以得到:
Promise的特点:
- 对象的状态不受外界影响 => 想要改变状态 需要借助 resolve,rejected 方法 resolve() => pending(进行中状态) => fulfilled(已成功) reject() => pending(进行中状态) => rejected(已失败)
- Promise 对象 的状态一经改变 不能再次改变
Promise的优点:
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
Promise的缺点:
- 无法取消Promise,一旦新建它就会立即执行,无法中途取消。
- 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。(直接报错)
- 当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。