您的位置:首页 > 其它

Promise简介

2020-06-26 04:24 155 查看

1、promise是什么?
(1) 关于promise
① 抽象表达:promise是JS进行异步编程的新的解决方案。
② 具体表达:promise是一个构造函数,promise对象用来封装一个异步操作并可以获取其结果。

(2) promise的状态改变
promise的初始状态(new Promise 的时候)为 pending,状态的改变只有以下两种:
① pending 变为 resolved (成功)
② pending 变为 rejected (失败)
注:只有这两种状态的变化,一个promise对象只能改变一次,无论成功还是失败都会有一个结果数据。(成功的数据为 value;失败的数据为 reason)

(3) promise的基本流程


excutor 执行器函数 :同步执行,会在promise内部立即同步执行,而异步操作则在执行器函数excutor中执行。 (resolve,reject) => { }

2、为什么要用promise?
(1)、指定回调函数的方式更加灵活,可以在请求发出后甚至结束后再指定回调函数。
① 旧的方法(纯回调):必须在启动异步任务前指定回调函数。
② promise:可以在请求发出后甚至结束后再指定回调函数。

(2)、支持链式调用,解决回调地狱问题
回调地狱:回调函数嵌套调用,后一个任务的执行以前一个任务成功为前提;回调地狱的缺点是代码不便于阅读、不便于异常处理。

(3)、补充
① promise为什么可以链式调用? 因为每个 then 都会返回(return)一个新的 promise对象。
② 解决回调地狱的另一种方案: async / await

3、promise的几个关键问题
(1)、promise的状态改变和回调函数的指定,两者的先后顺序:
① 一般情况下是先指定回调函数,然后再改变状态,如:

new Promise((resolve, reject) => {
setTimeout(() => { //异步操作
resolve(1) // 后改变状态
}, 0);
}).then(
// 先指定回调函数, 保存当前指定的回调函数
value => {
},
reason => {
console.log('reason:', reason)
}
)

② 也可以先改变状态,后指定回调函数,如:

new Promise((resolve, reject) => {
resolve(1)   // 先改变的状态  (在执行器函数里面,同步执行这句话后再执行 then 回调函数)
}).then(
// 后指定回调函数
value => {
console.log('value:', value)
},
reason => {
console.log('reason:', reason)
}
)

(2)、promise.then() 返回的新promise结果状态由什么决定?
是由 then() 指定的回调函数执行的结果决定的:
① 如果返回的是另一个新promise, 这个promise的结果就会成为新promise的结果
② 如果返回的是非promise的任意值, 新promise状态变为resolved, value为返回的值
③ 如果抛出异常, 新promise状态变为rejected, reason为抛出的异常

new Promise((resolve, reject) => {
resolve(1)  // 1、成功,则执行下一个 then() 的成功函数
//reject(1)
}).then(
value => {
console.log('onResolved1()', value)  // 2、输出  onResolved1() 1
// return 2     // 非promise的任意值 成功
// return Promise.resolve(3)  // 成功
// return Promise.reject(4) // 失败
throw 5   // 3、抛出错误,执行下一个 then() 的失败函数
},
reason => {
console.log('onRejected1()', reason)
// return 2
// return Promise.resolve(3)
// return Promise.reject(4)
throw 5
}
).then(
value => {
console.log('onResolved2()', value)
},
reason => {
console.log('onRejected2()', reason) // 4、输出 onRejected2() 5
}
)

(3)、promise 异常传透
当使用promise 的 then() 链式调用时,在最后用 catch() 指定失败的回调,前面操作出现了异常,都会传到最后的catch() 失败的回调函数中处理。(即在 then() 里面不写失败的回调函数,而统一在最后写 catch() 失败的回调处理函数,前面出现异常时,会一层一层传到最后的 catch() 回调函数中)

new Promise((resolve, reject) => {
resolve(1) // 成功
}).then(
value => {
console.log('onResolved1()', value) //输出 onResolved1() 1
return 2  // 成功
}
).then(
value => {
console.log('onResolved2()', value) // 输出 onResolved2() 2
throw 3  // 失败,后面的 then() 都没有失败处理回调函数,则会一直往后传,传到 catch() 中
}
).then(
value => {
console.log('onResolved3()', value)
}
).catch(reason => {  // catch() 失败处理回调函数
console.log('onReejected1()', reason) // 输出 onReejected1() 3
})

(4)、如何中断 promise链?
中断promise链:即在使用 then() 链式调用时,在中间中断,不在调用后面的回调函数。
实现的方法:在当前的回调函数中返回 return 一个 pending状态的promise对象。(可简单粗暴的理解成返回一个空的 promise对象)

new Promise((resolve, reject) => {
resolve(1) // 成功
}).then(
value => {
console.log('onResolved1()', value)
return 2  // 成功
},
reason => {
console.log(reason)
return 3
}
).then(
value => {
console.log('onResolved2()', value)
return new Promise(() => { })
/* 返回一个 pending状态的 promise对象(空promise对象),返回的状态既不是resolved也不是rejected
所以在下一个 then 中的回调函数不会执行,从而达到链中断的目的 */
}
).then(
value => {
console.log('onResolved3()', value)
},
reason => {
console.log(reason)
return 4
}
)

4、promise.all() 与 promise.race()
promise.all() :传入一个数组,包含n个promise对象,只有传入的promise对象都为成功时返回的才是成功,否则返回失败;
promise.race() :传入一个数组,包含n个promise对象,在n个promise对象中,只保留取最先执行完成的 promise对象的异步操作结果 (其他的仍会执行,但结果会被抛弃)。

let p1 = Promise.resolve('成功了执行resolve(),Promise状态变为resolved');  //成功
let p2 = Promise.resolve(`成功了执行resolve(),Promise状态变为resolved`);  //成功
let p3 = Promise.reject('失败执行reject(),Promise状态变为rejected');      //失败

// 所有的成功才算成功,只要有一个失败就失败
const promise = Promise.all([p1, p2, p3]); // 有一个是失败的,所以是失败
promise.then(value => {
console.log("成功:", value)
}, reason => {
console.log("失败:", reason) // 输出  失败:失败执行reject(),Promise状态变为rejected
})

// 谁先执行完就返回谁
const rece = Promise.race([p1, p2, p3]);  // p1最先执行完 故返回 p1 的结果
rece.then(value => {
console.log("成功:", value)  // 输出  成功:成功了执行resolve(),Promise状态变为resolved
}, reason => {
console.log("失败:", reason)
})
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: