1、Promise创建后会立即执行,then或者catch中为异步任务
let promise = new Promise(function (resolve, reject) {
console.log(111)
resolve()
})
promise.then(() => {
console.log(222)
})
console.log(333)
// 111
// 333
// 222上面代码中,Promise新建后会立即执行,首先打印111。然后then方法指定的回调函数为异步任务,应在同步任务(打印333)执行后再执行,因此打印222最后执行。
2、调用resolve或reject并不会终结 Promise 的参数函数的执行
const p = new Promise(function (resolve, reject) {
resolve(1)
console.log(2)
})
p.then((value) => {
console.log(value)
})
// 2
// 1实例对象p调用resolve(1)后,后面的console.log(2)还是会执行,并且会首先打印,这是因为立即 resolved 的 Promise 是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。
一般来说,调用resolve或reject之后,Promise的使命就完成了,后继操作应该放在then方法里,而不应该直接写在resolve或reject的后面,所以最好在他们前面加上return语句。
const p = new Promise(function (resolve, reject) {
return resolve(1)
console.log(2) // 该语句不再执行
})
p.then((val) => {
console.log(val)
})
// 13、resolve函数的参数除了正常的值以外,还可能是另一个Promise实例
const p1 = new Promise(function (resolve, reject) {
// some code ...
})
const p2 = new Promise(function (resolve, reject) {
resolve(p1)
})p2的resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作。p1的状态会传递给p2,也就是说,p1的状态决定了p2的状态,如果p1的状态是pending,那么p2的回调函数就会等待p1的状态改变,当p1的状态变为resolved或者rejected时,p2的回调函数将会立即执行。
const p1 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(111), 3000)})
const p2 = new Promise(function (resolve, reject) {
setTimeout(() => resolve(p1), 1000)
})
p2.then(result => console.log(result))
.catch(err => console.log(err))
111 // 3秒后打印上面例子中p1是一个Promise,3秒后变为resolved。而p2的状态在1秒之后改变,resolve方法返回的是p1。由于p2也是一个Promise,此时p2自己的状态无效,p2后面的then方法由p1决定,2秒后p1变为resolved触发then方法指定的回调函数。
4、Promise.prototype.then()
Promise的then方法是定义在原型对象Promise.prototype上的,then方法返回的是一个新的Promise实例,不是原来的那个Promise实例,因此可以采用链式写法。
const p = new Promise(function (resolve, reject) {})
p.then(() => {})
.then(() => {})
...5、Promise.prototype.catch()
Promise.prototype.catch()方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。
const p = new Promise(function (resolve, reject) {
if (condition) {
resolve()
} else {
reject()
}
})
p.then((success) => {})
.catch((err) => {})实例对象p状态变为resolved,就会调用then方法指定的回调函数,如果变为rejected,则调用catch方法指定的回调函数。另外then方法回调函数如果运行中抛出错误,也会被catch方法捕获。
如果Promise状态已经变为resolved,再抛出错误是无效的,如下代码:
const p = new Promise(function (resolve, reject) {
resolve('ok')
throw new Error('fail')
})
p.then(value => console.log(value))
.catch(error => console.log(error))
ok // Error信息不会被捕获Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止。
const p = new Promise(function (resolve, reject) {})
p.then(() => {})
.then(() => {})
.then(() => {})
.catch((error) => {})
//三个then方法任何一个抛出错误都会被catch捕获6、Promise.all()
Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
const p = new 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的回调函数。
如果作为参数的Promise实例,自己定义了catch方法,那么它一旦rejected,并不会触发Promise.all()的catch方法。只有参数在rejected状态下未定义catch方法才会触发Promise.all()的catch方法。
7、利用Promise判断图片是否加载完成
function loadImg(url) {
return new Promise(function (resolve, reject) {
const image = new Image()
image.onload = function () {
resolve()
}
image.onerror = function () {
reject()
}
image.src = url
})
}