Promise之执行器
本质上Promise就是一个构造函数。
Promise的实例对象有三个状态
pending: 初始状态,既不是成功,也不是失败状态。
fulfilled: 意味着操作成功完成。(resolved)
rejected: 意味着操作失败
Promise语法
new Promise( function(resolve, reject) {…}); //第一个参数一般我们称为executor
//实例
var promise = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, ‘foo’);
});
executor
executor是带有 resolve 和 reject 两个参数的函数 。Promise构造函数执行时立即调用executor 函数,在实例对象被返回前。resolve 和 reject 两个函数作为参数传递给executor。resolve 和 reject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。executor 内部通常会执行一些异步操作,一旦完成,可以调用resolve函数来将promise状态改成fulfilled,或者在发生错误时调用reject函数将它的状态改为rejected。如果在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。
执行器是一个同步的回调函数
执行器是一个高阶函数
大忌:不能再执行器中直接同步的决定promise的状态
promise实例对象具有三个状态:初始化状态,成功状态,失败状态
promise实例对象的状态可以触发一系列回调的这个事是一次性的!!!
promise实例对象的状态切换 是我们学习promise的核心
promise实例对象是可以拥有值!!!
先有执行器的调用,才有promise实例对象的生成
var promise = new Promise(function (resolve, reject) {
//再执行器中一定要抒写异步代码
//让定时器来模拟ajax请求
setTimeout((flag,data)=>{
if(flag){
//请求成功
resolve(data)
}else{
//请求失败
reject("网络断了!!!")
}
},1000,true,"one")
//当前返回的promise具备了实际的意义 当它的状态产生改变时 代表的就是我们的请求成功与否!
})
Promise.prototype.then
当promise对象的状态发生改变时,绑定在其身上的then方法中的两个参数会被选择性的注册一个。
then方法包含两个参数:onfulfilled函数 和 onrejected函数,它们都是 Function 类型。当Promise状态为fulfilled时,注册 then 的 onfulfilled 方法,当Promise状态为rejected时,注册 then 的 onrejected 方法, 所以在异步操作的完成和绑定处理方法之间不存在竞争
then() 方法返回一个 Promise 。
// 关注then方法返回的promise的状态是如何改变的!值又是如何分配的!
// 最佳实践 then方法的回调参数中一定要返回一个promise
new Promise(function (resolve, reject) {
setTimeout((flag,data)=>{
if(flag){
resolve(data)
}else{
reject("网络断了!!!")
}
},1000,true,"one")
})
.then((data)=>{
console.log("第一次数据获取成功:"+data);
return new Promise((resolve, reject)=>{
setTimeout((flag,data)=>{
if(flag){
resolve(data)
}else{
reject("网络断了!!!")
}
},1000,true,"two")
})
})
.then((data)=>{
console.log("第二次数据获取成功:"+data);
return new Promise((resolve, reject)=>{
setTimeout((flag,data)=>{
if(flag){
resolve(data)
}else{
reject("网络断了!!!")
}
},1000,true,"three")
})
})
.then((data)=>{
console.log("第三次数据获取成功:"+data);
})
async&await
正常函数前加一个async关键字后,该函数就被定义成了一个async函数。
当调用一个 async 函数时,会返回一个 Promise 对象。
当这个 async 函数返回一个值时,Promise 的 resolve 方法会负责传递这个值;
当 async 函数抛出异常时,Promise 的 reject 方法也会传递这个异常值。
await
await 操作符用于等待一个Promise 对象。它只能在async function 中使用。
await 表达式会暂停当前 async function 的执行,等待 Promise 处理完成。
若 Promise 正常处理(fulfilled),!!其回调的resolve函数参数作为 await 表达式的值!!,继续执行 async function。
若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。
/* async函数返回的promise的 状态&持有的值
当async函数返回一个非promise的值时;async函数返回的promise;变为成功状态;持有的值是async函数返回的值
当async函数返回一个promise时 那就看这个promise的状态和值
当async函数抛出异常时;async函数返回的promise变为失败状态;持有的值是异常信息*/
async function test() {
console.log("test");
throw new Error("0000")
}
var promise = test()
console.log(promise);
await
async function test() {
const data1 = await new Promise(function (resolve, reject) {
setTimeout((flag,data)=>{
if(flag){
resolve(data)
}else{
reject("网络断了!!!")
}
},1000,true,"one")
});
console.log("第一次数据获取成功:"+data1);
const data2 = await new Promise((resolve, reject)=>{
setTimeout((flag,data)=>{
if(flag){
resolve(data)
}else{
reject("网络断了!!!")
}
},1000,true,"two")
})
console.log("第二次数据获取成功:"+data2);
const data3 = await new Promise((resolve, reject)=>{
setTimeout((flag,data)=>{
if(flag){
resolve(data)
}else{
reject("网络断了!!!")
}
},1000,true,"three")
})
console.log("第三次数据获取成功:"+data3);
}
test()
async的异常处理
async function test() {
// try {
const data1 = await new Promise(function (resolve, reject) {
setTimeout((flag,data)=>{
if(flag){
resolve(data)
}else{
reject("网络断了!!!")
}
},1000,false,"one")
});
console.log("第一次数据获取成功:"+data1);
const data2 = await new Promise((resolve, reject)=>{
setTimeout((flag,data)=>{
if(flag){
resolve(data)
}else{
reject("网络断了!!!")
}
},1000,true,"two")
})
console.log("第二次数据获取成功:"+data2);
const data3 = await new Promise((resolve, reject)=>{
setTimeout((flag,data)=>{
if(flag){
resolve(data)
}else{
reject("网络断了!!!")
}
},1000,true,"three")
})
console.log("第三次数据获取成功:"+data3);
// }catch (e) {
// console.log(e,"-----");
// }
}
test().catch((err)=>{
console.log(err);
})
1、promise面试题
输出值问题
同步:1,7,2,3
微队列:8,4,6,5
宏队列:0
// 输出: 1 7 2 3 8 4 6 5 0
setTimeout(() => {console.log("0")}, 0)
new Promise((resolve,reject)=>{
console.log("1")
resolve()
}).then(()=>{
console.log("2")
new Promise((resolve,reject)=>{
console.log("3")
resolve()
}).then(()=>{
console.log("4")
}).then(()=>{
console.log("5")
})
}).then(()=>{
console.log("6")
})
new Promise((resolve,reject)=>{
console.log("7")
resolve()
}).then(()=>{
console.log("8")
})
先执行同步输出,
因为new Promise里面的回调函数是异步,v8引擎先执行后面的几个then方法,调用线程池里面的线程来持有then,根据得到状态的先后顺序分别把他们放入微队列中,等待v8来顺序执行。先进的先执行,执行完了才能接着放下一个等待被放入的持有then线程.
要分清楚回调函数的注册和执行,他们是分开的,回调函数什么时候会被执行,v8有空了,就会被执行。
同级的谁在前就先把谁放微队列。
例如,两个并行的new Promise
先输出第一个的1,再输出第二个的7,
然后同级别的then也是谁在前先把谁放入微队列。
满足条件之后:先2*+,再8
满足条件之后:先4,再6
2、异常错误的传递
new Promise((resolve, reject)=>{
setTimeout(()=>{
reject("xxx")
},2000)
})
.then(()=>{})
.then(()=>{})
.then(()=>{})
.then(()=>{})
.catch((reason)=>{console.log(reason);})
reject抛出异常以后,后面的.then只有写一个参数才能将异常信息传递到最后一个catch哪里去。
如果写了第二个参数来接收,返回值为undefined,那么then的返回的promise状态就会为成功。最后的catch接收不到异常。
async面试题:
async function test() {
await new Promise(function(resolve, reject){
setTimeout(function(){
console.log(1)
resolve()
},2000)
})
}
(async ()=>{
await test()
console.log(2)
})()
使用一个自调用async来包裹另外一个async test()函数 在他的前面加上await来卡点,达到先执行异步回调函数,再来执行同步回调,提高代码的易读性。
错误的await代码,切记await 后面一定要跟new promise
// await 后一定要跟promise!!!!
Promise.resolve(1).then((data1)=>{
console.log("第一次数据获取成功:"+data1);
return 2
}).then((data2)=>{
console.log("第二次数据获取成功:"+data2);
return 3
}).then((data3)=>{
console.log("第三次数据获取成功:"+data3);
})
/*async function test() {
const data1 = await 1
console.log("第一次数据获取成功:"+data1);
const data2 = await 2
console.log("第二次数据获取成功:"+data2);
const data3 = await 3
console.log("第三次数据获取成功:"+data3);
}
test()*/
Promise笔记
可以返回一个promise的api
new Promise((resolve,reject)=>{})
状态&持有的值
默认是初始化状态;持有的值是undefined
当执行器的第一个参数resolve(val)被调用时;promise变为成功状态;持有的值是val
当执行器的第二个参数reject(reason)被调用时;promise变为失败状态;持有的值是reason
当执行器抛出异常时;promise变为失败状态;持有的值是异常信息
Promise.prototype.then(onResolve,onReject)
状态&持有的值
默认是初始化状态;持有的值是undefined
当then的任意一个回调进入队列并被执行后;then返回的promise的状态就可以确定了
当这个回调返回一个非promise的值时;then返回的promise;变为成功状态;持有的值是这个回调返回的值
当这个回调返回一个promise时;then返回的promise和回调返回的promise保持一致
当这个回调抛出异常时;then返回的promise变为失败状态;持有的值是异常信息
promise的状态机制
当promise发生改变时;如果其已经调用了then方法;那then方法中两个参数;会被选择性的塞入到队列中
如果promise变为成功状态 则then的第一个参数进微队列
如果promise变为失败状态 则then的第二个参数进微队列