总结规则
1.要看定义的时候定义的是值还是函数
值会在定义的时候就赋值,执行new Promise
函数,只有在执行的时候才会调用{}中的内容
//定义promise1为Promise的实例对象
const promise1 = new Promise((resolve, reject) => {
console.log('promise1')
resolve('resolve1')
})
//定义fn为一个函数,在函数里新建了一个Promise的实例对象
const fn = () =>
new Promise((resolve, reject) => {
console.log(1);
resolve("success");
});
2.Promise打印出来的内容是
Promise {<pending>:}
Promise {<fulfilled>: resolve中的值}(如果是空括号,值为undefined)
Promise {<rejected>: reject中的值}
(上面是V8引擎下的结果,在Node.js中为Promise {<pending>:}、Promise {resolve中的值}、Promise {<rejected>: reject中的值}。fulfilled状态下的Promise对象中只包含值)
3.Promise.then()中的then会加入到微任务队列且是必须加到微任务队列中等待同步任务执行完再取出来,但是取出来执行的条件是Promise的状态为fulfilled或rejected(取决于then中的回调)
4.先执行同步任务,碰到异步宏任务加入宏任务队列,碰到异步微任务加入微任务队列,同步任务执行完从微任务中把所有微任务执行完,再去宏任务队列中执行宏任务。
5.V8引擎中,抛出一个错误后会继续进行后面的代码。
但在Node.js中,报错了之后会中断运行
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 1000)
})
const promise2 = promise1.then(() => {
throw new Error('error!!!')
})
console.log('promise1', promise1)
console.log('promise2', promise2)
setTimeout(() => {
console.log('promise1', promise1)
console.log('promise2', promise2)
}, 2000)
//在v8引擎中:
//'promise1' Promise{<pending>}
//'promise2' Promise{<pending>}
//Uncaught (in promise) Error: error!!! at <anonymous>:7:9
//'promise1' Promise{<resolved>: "success"}
//'promise2' Promise {<rejected>: Error: error!!! at <anonymous>:7:9}
//在node.js中
//promise1 Promise { <pending> }
//promise2 Promise { <pending> }
//d:\VScode\workspace\lianxi\handwrite.js:7
// throw new Error('error!!!')
^
//Error: error!!!
// at d:\VScode\workspace\lianxi\handwrite.js:7:9
6.Promise的状态是不可逆的,只能从pending变成fulfilled或pending变成rejected
const promise = new Promise((resolve, reject) => {
resolve("success1");
reject("error");
resolve("success2");
});
console.log(promise);
//Promise {<fulfilled>: 'success1'}
- 出现.then要仔细看.then中是只处理fulfilled状态还是fulfilled状态和rejected状态都能处理。如果.then中只有一个参数那就是只能处理fulfilled状态。then自动会返回一个Promise,如果没指定return,那就是return Promise(undefined),这使得.then可以一直链式调用
但.catch不管被连接到哪里,都能捕获上层未捕捉过的错误,不管前面是否有未执行的.then。而catch自动会返回一个Promise,如果没指定那就是undefined
const promise = new Promise((resolve, reject) => {
reject("error");
resolve("success2");
});
promise
.then(res => {
console.log("then1: ", res);
}).then(res => {
console.log("then2: ", res);
}).catch(err => {
console.log("catch: ", err);
}).then(res => {
console.log("then3: ", res);
})
//catch: error
//then3: undefined
8.如果Promise.then返回的是一个值,默认会包裹一层Promise.resolve,使得返回的是一个Promise对象。
Promise.catch返回的是一个值,也会包裹一层Promise.resolve! 是fulfilled状态的!!!
Promise.reject(1)
.then(res => {
console.log(res);
return 2;
})
.catch(err => {
console.log(err);
return 3
})
.then(res => {
console.log(res);
});
//1
//3
9.Promise.then中返回的任意一个非Promise对象都会被包装成Promise对象,包 new Error!!
Promise.resolve().then(() => {
return new Error('error!!!')
}).then(res => {
console.log("then: ", res)
}).catch(err => {
console.log("catch: ", err)
})
//then: Error: error!!! at <anonymous>:2:10
//而且不会报错
如果想抛出一个错误,可以直接throw new Error(‘error!!!’) 不放在return 中,或者返回一个rejected状态的Promise
//修改后
Promise.resolve().then(() => {
throw new Error('error!!!')
}).then(res => {
console.log("then: ", res)
}).catch(err => {
console.log("catch: ", err)
})
//catch: Error: error!!! at <anonymous>:2:9
或
Promise.resolve().then(() => {
return Promise.reject(new Error('error!!!'))
}).then(res => {
console.log("then: ", res)
}).catch(err => {
console.log("catch: ", err)
})
//catch: Error: error!!! at <anonymous>:2:25
- .then 或 .catch 返回的值不能是 promise 本身,否则会造成死循环,结果会报错。
const promise = Promise.resolve().then(() => {
return promise;
})
promise.catch(console.err)
//报错:
//Uncaught (in promise) TypeError: Chaining cycle detected for promise #<Promise>
- .then和.catch期望参数是函数,如果不是函数只是一个值,那么会发生透传,传给下一个.then或.catch
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
//1
- .finally()方法不管Promise对象最后的状态如何都会执行
.finally()方法的回调函数不接受任何的参数,也就是说你在.finally()函数中是没法知道Promise最终的状态是resolved还是rejected的
它最终返回的默认会是一个上一次的Promise对象值(自己返回的值无效),不过如果抛出的是一个异常则返回异常的Promise对象。
Promise.resolve('1')
.then(res => {
console.log(res)
})
.finally(() => {
console.log('finally')
})
Promise.resolve('2')
.finally(() => {
console.log('finally2')
return '我是finally2返回的值'
})
.then(res => {
console.log('finally2后面的then函数', res)
})
//1
//finally2
//finally
//finally2后面的then函数 2
这里有两个Promise.resolve(‘1’),Promise.resolve(‘2’)同步任务,不要忘了把微任务放微任务队列
13.await会阻塞后面的代码!!!await 当前那句会立刻执行,await下面的语句相当于.then 放入微任务队列!!
async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log("async2");
}
async1();
console.log('start')
//'async1 start'
//'async2'
//'start'
//'async1 end'
- 记得查看Promise中是否有返回值
async function async1 () {
console.log('async1 start');
await new Promise(resolve => {
console.log('promise1')
})
console.log('async1 success');
return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')
//'script start'
//'async1 start'
//'promise1'
//'script end'
在async1中await后面的Promise是没有返回值的,也就是它的状态始终是pending状态,因此相当于一直在await,await,await却始终没有响应…
所以在await之后的内容是不会执行的,也包括async1后面的 .then。
15.函数中存在new Promise,但不是返回new Promise
async function async1 () {
await new Promise(resolve => {
resolve('promise resolve')
})
return 'async1 end'
}
async1().then(res => {
console.log(res)
})
//async1 end
resolve里的值是返回的值’async1 end’
async function async1 () {
await new Promise((resolve,reject) => {
reject('promise resolve')
})
return 'async1 end'
}
async1().catch(res => {
console.log(res)
})
//promise resolve
reject里的值是本身参数’promise resolve’
神奇,不知道为啥,记住吧!
- 函数中存在new Promise,且还返回new Promise
async function async1 () {
try {
await Promise.reject('error!!!')
} catch(e) {
console.log(e)
}
console.log('async1');
return Promise.resolve('async1 success')
}
async1().then(res => console.log(res))
console.log('script start')
//'script start'
//'error!!!'
//'async1'
//'async1 success'
以最后返回的Promise.resolve(‘async1 success’)为准
- await 后面的要是一个fulfilled状态的Promise,但经过了await就能拿到Promise里具体值
async function testAsync() {
return Promise.resolve("hello async");
}
const v2 = await testAsync();
console.log(v2)
//hello async
await后面要是一个rejected状态的Promise,经过await会报错,并不再继续执行
async function async1 () {
await async2();
console.log('async1');
return 'async1 success'
}
async function async2 () {
return new Promise((resolve, reject) => {
console.log('async2')
reject('error')
})
}
async1().then(res => console.log(res))
//async2
//报错 Uncaught (in promise) error
18.练习
const async1 = async () => {
console.log('async1');
setTimeout(() => {
console.log('timer1')
}, 2000)
await new Promise(resolve => {
console.log('promise1')
})
console.log('async1 end')
return 'async1 success'
}
console.log('script start');
async1().then(res => console.log(res));
console.log('script end');
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.catch(4)
.then(res => console.log(res))
setTimeout(() => {
console.log('timer2')
}, 1000)
//'script start'
//'async1'
//'promise1'
//'script end'
//1
//'timer2'
//'timer1'
async函数中await的new Promise要是没有返回值的话则不执行后面的内容
.then函数中的参数期待的是函数,如果不是函数的话会发生透传
注意定时器的延迟时间
const p1 = new Promise((resolve) => {
setTimeout(() => {
resolve('resolve3');
console.log('timer1')
}, 0)
resolve('resovle1');
resolve('resolve2');
}).then(res => {
console.log(res)
setTimeout(() => {
console.log(p1)
}, 1000)
}).finally(res => {
console.log('finally', res)
})
//'resolve1'
//'finally' undefined
//'timer1'
//Promise{<resolved>: undefined}
Promise的状态一旦改变就无法改变
finally不管Promise的状态是resolved还是rejected都会执行,且它的回调函数是接收不到Promise的结果的,所以finally()中的res是一个迷惑项。
最后一个定时器打印出的p1其实是.finally的返回值,我们知道.finally的返回值如果在没有抛出错误的情况下默认会是上一个Promise的返回值,而这道题中.finally上一个Promise是.then(),但是这个.then()并没有返回值,所以p1打印出来的Promise的值会是undefined,如果你在定时器的下面加上一个return 1,则值就会变成1。