一、实例对象和函数对象:
函数对象:将函数作为对象使用时,简称为函数对象,操作它的属性或方法时,用.
实例对象:new 函数产生的对象,简称对象
JS只所有函数都是Function类的实例对象,call()、bind()、apply()都函数对象才有的方法,在原型上
<script type='text/javascript'>
//js中所有函数都是Function类的实例对象
function Fn () { //Fn函数
}
const fn = new Fn() //Fn是构造函数, fn是实例对象(简称为对象)
console.log(Fn.prototype); //Fn是函数对象
/**
* bind()方法主要就是将函数绑定到某个对象,bind()会创建一个函数,函数体内的this对象的值会被绑定到传入bind()第一个参数的值,
* 例如,f.bind(obj),实际上可以理解为obj.f(),这时,f函数体内的this自然指向的是obj
*/
Fn.bind({}) //Fn是函数对象
$('#test') // (jQuery函数) $是一个函数,根据选择器查找DOM元素 -- 括号的左边是函数
$.get('/test') // (jQuery函数对象) 调用$函数对象的get方法 ---- 点的左边是对象
</script>
二、二种类型的回调函数:
1、什么是回调函数
必须是自己定义的
我不会亲自调用
会自己执行
例如setTimeout()中传递的回调函数
2、回调函数的两种类型
同步回调
理解:立即执行,完全执行完了才结束,不会放入回调队列中
例子:数组遍历相关的回调函数/ promise的excutor函数
异步回调
理解: 不会立即执行,会放入回调队列中将来执行
例子:定时器回调 / ajax回调 / promise的成功|失败回调
<script type='text/javascript'>
/**
* 1.同步回调函数
*/
const arr = [1, 2, 3, 4, 5]
arr.forEach(item => { //遍历回调,同步回调函数(就是说只有把forEach里面的回调函数执行完了,foreach才会结束),不会放入队列
console.log(item);
})
console.log('foreach()之后');
/**
* 2.异步回调函数
*/
/**
* js中两种定时器,setTimeout和setInterval的区别
* setTimeout只在指定时间后执行一次
* setInterval以指定时间为周期循环执行
*/
setTimeout(() => { //异步回调函数,会放入队列中将来执行
console.log('timeout callback()');
}, 0)
console.log('setTimeout()之后执行');
</script>
三、JS中的error处理:
1、Error常见的错误类型及处理方法:
Error:所有错误的父类型
(1)ReferenceError:引用的变量不存在
(2)TypeError:数据类型错误
(3)RangeError:数据不在其允许的范围内
(4)SyntaxError:语法错误
2、错误的处理:
(1)捕获错误:try...catch
把可能出现的错误,放在try语句中
例如以下的例子:
try{
let b;
console.log(b.xxx);
}catch(Error){
console.log(Error);
}
(2)抛出错误:throw error
function sth(){
if(Date.now()%2===0){
console.log("当前时间为偶数");
}else{
throw new Error('当前时间为基数'); //抛出异常
}
}
//捕获异常
try{
sth();
}catch(error){
console.log("error:",error.message);
}
console.log("可以正常执行该代码!!");
3、错误对象:
message属性:错误的信息
stack:函数调用栈记录信息
四、Promise的理解和使用
1、Promise是什么?
抽象表达:Promise是JS中进行异步编程的新的解决方案(旧的是谁?===〉纯回调形式)
具体表达:
从语法上说:Promise是一个构造函数;
从功能上说:Promise对象用来封装一个异步操作并可以获取其结果;
Promise状态改变:
pending变为resolved 【成功】
pending变为rejected 【失败】
说明:只有这两种,且一个promise对象只能改变一次;
无论变为成功还是失败,都会有一个结果数据;
成功的结果数据一般称为value,失败的结果数据一般称为reason;
Promise的基本流程:
promise的基本使用
<script type='text/javascript'>
// 1.创建一个新的promise对象
const p = new Promise((resolve , reject) => { //执行器函数, 是一个同步回调
console.log('执行 excutor')
// 2.执行异步任务
setTimeout(() => {
const time = Date.now() //如果当前时间为偶数代表成功,否则失败
// 3.1 如果成功了,调用resolve(value)
if(time % 2 === 0){
resolve('成功的数据,time =' + time)
}else{
//3.2 如果失败了,调用reject(reason)
reject('失败的数据,time=' + time)
}
},1000)
})
console.log('new promise()执行之后')
p.then(
value => {//接收得到成功的value数据 onResolved
console.log('成功的回调',value);
},
reason => {//接收得到失败的reason数据 onRejected
console.log('失败的回调',reason);
}
)
</script>
2、为什么要用Promise?(重点)
指定回调函数的方式更加灵活
旧的:必须在启动异步任务之前指定
promise: 启动异步任务 => 返回promise对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定)
支持链式调用,可以解决回调地狱问题
什么是回调地狱?回调函数嵌套调用,外部回调函数异步执行的结果是嵌套的回调函数执行的条件
回调地狱的缺点?不便于阅读 / 不便于异常处理
解决方案? promise链式调用 【一个Promise对应一个异步任务】
dosomething()
.then(result=>{
return doSomethingElse(result)
}).then(newresult=>{
return doSomeThingOther(finalResult)
}).then(finalResult=>{
console.log("最终结果:"+finalResult)
}).catch(failureCallBack); //异常传透!,当以上任意一个Promise有问题,都会调用失败回调函数
终极解决方案? async/await
async function request(){
try{
const result=await doSomething();
const newresult=await doSomeThingElse(result);
const finalResult=await doSomeThingOther(newresult);
console.log("最终结果:"+finalResult)
}
}catch(error){
failureCallBack(error);
};
什么时候会出现地狱回调?多个串联的异步操作
3、如何使用Promise?
API:语法/前后台交互的接口
(1)promise构造函数:Promise(excutor){}
excutor函数:执行器 (resolve,reject) => {}
resolve函数:内部定义成功时调用的函数 value => {}
reject函数:内部定义失败时我们调用的函数 reason => {}
说明:excutor会在Promise内部立即同步回调,异步操作在执行器中执行
(2)Promise.prototype.then方法:(onResolved , onRejected) => {}
onResolved函数:成功的回调函数 value => {}
onRejected函数:失败的回调函数 reason => {}
说明:指定用于得到成功value的成功回调函数和用于得到失败reason的失败回调函数,返回一个新的promise对象==>这是Promise链式调用的前提
(3)Promise.prototype.catch方法:(onRejected) => {}
onRejected函数:失败的回调函数 (reason) => {}
then的语法糖,相当于then(undefined,onRejected)【语法糖:某种语法的简写方式】
(4)Promise.resolve方法:value => {}
value: 成功的数据或者promise对象
说明:返回一个成功/失败的promise对象
(5)Promise.reject方法:(reason) => {}
reason:失败的原因
说明:返回一个失败的promise对象
(6)Promise.all方法:(promises) => {}
promises:包含n个promise的数组
说明:返回一个新的promise,只有所有的promise都成功才算成功,只要有一个失败了就直接失败
(7)Promise.race方法:(promises) => {}
promises:包含n个promise数组
说明:返回一个新的promise,第一个完成的promise的结果状态就是最终的状态
<script type='text/javascript'>
new Promise((resolve , reject) => {
//执行异步任务
setTimeout(() => {
//resolve('成功的数据')
reject('失败的数据')
}, 1000)
}).then(
value => {
console.log('onResolved()1', value);
}
).catch(
reason => {
console.log('onRejected()1' , reason);
}
)
// 产生一个成功值为1的promise对象
const p1 = new Promise((resolve , reject) => {
resolve(1)
})
const p2 = Promise.resolve(2)
//产生一个失败值为3的promise对象
const p3 = Promise.reject(3)
p1.then( value => { console.log(value); })
p2.then( value => { console.log(value); } )
p3.catch( reason => { console.log(reason); })
const pAll = Promise.all([p1 , p2])
pAll.then(
values => {
console.log('all onResolved()',values);
},
reasons => {
console.log('all onRejected()',reasons);
}
)
const Prace = Promise.race([p3, p2, p1])
Prace.then(
value => {
console.log('on Resolved()', value);
},
reason => {
console.log('on Rejected()',reason);
}
)
</script>
4、Promise的关键问题?
(1)如何改变Promise状态
resolve(value):如果当前是pendding就会变为resolved
reject(reason):如果当前为pendding就会变为rejected
抛出异常:如果当前为pendding就会变为rejected,失败的原因为抛出的内容
(2)一个Promise指定多个成功/失败的回调函数,都会调用吗?
当promise改变为对应状态时都会调用 【这样子的好处是,可以用同一个回调结果处理不同的业务逻辑】
<script type='text/javascript'>
const p = new Promise((resolve , reject) => {
// resolve(1) //promise变为resolved成功状态
// reject(2) // promise变为rejected失败状态
// throw new Error('出错') //抛出异常,promise变为rejected失败状态,reason为抛出的error
throw 3 //抛出异常,promise变为rejected失败状态,reason为抛出的3
})
p.then(
value => {
console.log('value1',value);
},
reason => {
console.log('reason1', reason);
}
)
p.then(
value => {
console.log('value2',value);
},
reason => {
console.log('reason2',reason);
}
)
</script>
(3)改变promise状态和指定回调函数谁先谁后?
A、都有可能,正常情况下是先指定回调再改变状态,但也可以先改变状态再指定回调
B、如何先改变状态再指定回调?
- 在执行器中直接调用resolve()/reject()
- 延长更长时间(setTimeout()函数)才调用then()
C、什么时候才能得到数据?
- 如果先指定的回调,那当状态发生改变时,回调函数就会调用,得到数据
- 如果先改变状态,那当指定回调时,回调函数就会调用,得到数据
<script type='text/javascript'> // 常规上先指定回调,会改变状态 new Promise((resolve , reject) => { setTimeout(() => { resolve(1) // 后改变的状态(同时指定数据),异步执行回调函数 },1000) }).then( //先指定回调函数,保存当前指定的回调函数 value => {}, reason => { console.log('reason' , reason); } ) //如何先改变状态后指定回调函数? //方法1:在执行器函数中直接调用resolve()/reject() new Promise((resolve , reject) => { resolve(1) // 先改变的状态(同时指定数据) }).then( //后指定回调函数,异步执行回调函数 value => {}, reason => { console.log('reason' , reason); } ) //方法2:延长更长的时间调用then const p= new Promise((resolve , reject) => { setTimeout(()=>{ resolve(1) // 先改变的状态(同时指定数据) },1000); }); setTimeout({ p.then( //后指定回调函数,异步执行回调函数 value => {}, reason => { console.log('reason' , reason); }); },1100); </script>
注意:同步指定状态,同步指定回调函数,.then和异步没有什么关联,只有,只有里边的回调函数是异步执行的,这个要区分开
Promise的成功或失败回调函数都是异步执行的,即使条件已经满足,状态等也已经改变,异步执行就意味着是放到队列里边,等待所有任务执行完了以后,才会去执行别的
(4) promise.then()返回的新的promise的结果状态由什么决定?
简单表达式:由then()指定的回调函数执行的结果决定
详细表达:
如果抛出异常,新promise变为rejected,reason为抛出异常
如果返回的是非promise任意值,新promise变为resolved,value为返回值
如果返回的是另一个新的promise,此promise的结果就会成为新promise的结果
<script type='text/javascript'>
new Promise((resolve , reject) => {
resolve(1)
}).then(
value => {
console.log('value',value);//1
//return value
//return Promise.resolve(3)
//return Promise.reject(4)
// throw 5
},
reason => {
console.log('reason',reason);
}
).then(
value => {
console.log('value1',value);//undefined
},
reason => {
console.log('reason1',reason);
}
)
</script>
(5)promise如何串联多个操作任务?
promise的then() 返回一个新的promise,可以看成then() 的链式调用
使用then的链式调用串联多个同步/异步任务
在回调函数中启动一个异步任务,一般封装成一个Promise对象
<script type='text/javascript'>
new Promise((resolve , reject) => {
setTimeout(() => {
console.log('执行异步任务1');
resolve(1)
},1000)
}).then(
value => {
console.log('任务1的结果',value);
console.log('执行同步任务2');
return 2
}
).then(
value => {
console.log('同步任务2的结果',value);
return new Promise((resolve , reject) => {
//执行异步任务3
setTimeout(() => {
console.log('执行异步任务3');
resolve(3)
},1000)
})
}
).then(
value => {
console.log('异步任务3的结果');
}
)
</script>
(6)promise异常穿透?
当使用promise的then链式调用时,可以在最后指定失败的回调
前面任何操作出现异常,都会传到最后失败的回调中处理
<script type='text/javascript'>
new Promise((resolve , reject) => {
//resolve(1)
reject(1)
}).then(
value => {
console.log('onResolve()1',value);
return 2
},
//异常穿透,相当于在每个then中 throw reason 或者 Promise.reject(reason)
// reason => {
// throw reason
// }
// reason => {
// Promise.reject(reason)
// }
).then(
value => {
console.log('onResolve()2',value);
return 3
}
).then(
value => {
console.log('onResolve()3',value);
}
).catch(
reason => {
console.log('onRejected()1',reason);
}
)
</script>
(7)中断promise链?
当使用promise的链式调用时,在中间中断,不再调用后面的回调函数
办法:在回调函数中返回一个pendding状态的promise对象 ,return new Promise(()=>{})
<script type='text/javascript'>
new Promise((resolve , reject) => {
reject(1)
}).then(
value => {
console.log('onResolve()1',value);
return 2
}
).then(
value => {
console.log('onResolve()3',value);
}
).catch(
reason => {
console.log('onRejected()1',reason);
return new Promise(() => {})//返回一个pending的promise,中断promise链
}
).then(
value => {
console.log('onResolve()4',value);
},
reason => {
console.log('onRejected()2',reason);
}
)
</script>
五、自定义(手写)Promise
1、ES5中如何定义模块?
在每个文件中使用立即执行函数来创建一个函数作用域,每个文件都互不干扰,就不会出现命名冲突的问题了。
但是如果每个文件都是独立的存在,互相之间没有任何关系,就没有了代码复用的可能,似乎带来的损失也不小。
所以,立即执行函数可以再返回一个对象,以便这些内部函数可以在词法作用域外被调用,从而形成一个闭包,然后将对象存于一个全局变量( module )中。
2、函数版本
/**
* 自定义promise函数模块,使用ES5语法
*/
//IIFE
(function (window) {
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
/**
* Promise构造函数
* excutor:执行器函数(同步执行)
*/
function Promise (excutor) {
//将当前promise对象保存起来
const self = this
self.status = PENDING //给promise对象指定status,初始值为pending
self.data = undefined // 给promise对象指定一个用于存储结果数据的属性
self.callbacks = [] // 每个元素结构:{ onResolved() {}, onRejected() {}}
function resolve (value) {
// 如果当前状态不是pending,直接结束
if (self.status !== PENDING) {
return
}
//将状态改为resolved
self.status = RESOLVED
//保存value数据
self.data = value
//如果有待执行的callbacks函数,立即异步执行回调函数onResolved
//说明是,先指定回调函数,后改变状态;那么就是在改变状态的时候,执行回调函数
if (self.callbacks.length > 0) {
setTimeout(() => { //放入队列中执行所有成功的回调
self.callbacks.forEach((callbacksObj) => {
callbacksObj.onResolved(value)
})
})
}
}
function reject (reason) {
// 如果当前状态不是pending,直接结束
if (self.status !== PENDING) {
return
}
//将状态改为rejected
self.status = REJECTED
//保存reason数据
self.data = reason
//如果有待执行的callbacks函数,立即异步执行回调函数onRejected
//说明是,先指定回调函数,后改变状态;那么就是在改变状态的时候,执行回调函数
if (self.callbacks.length > 0) {
setTimeout(() => { //放入队列中执行所有成功的回调
self.callbacks.forEach((callbacksObj) => {
callbacksObj.onRejected(reason)
})
})
}
}
//立即同步执行excutor
try {
excutor(resolve , reject)
}catch (error) { //如果执行器抛出异常,promise对象变为rejected
reject(error)
}
}
//promise原型对象的then():指定成功和失败的回调函数,返回一个新的promise对象
Promise.prototype.then = function (onResolved , onRejected) {
onResolved = typeof onResolved === 'function' ? onResolved : value => value //向后传递成功的value
//指定默认的失败回调(实现错误/异常穿透的关键步骤)
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason } //向后传递失败的reason
const self = this
//返回一个新的promise对象
return new Promise((resolve , reject) => {
//调用指定的回调函数处理,根据执行的结果改变return的promise状态
function handle (callback) {
try {
const result = callback(self.data)
if (result instanceof Promise) {
/*如果回调函数返回promise,return的promise结果就是这个promise的结果*/
// result.then(
// value => resolve(value), //当result成功时,让return的promise也成功
// reason => reject(reason) //当result失败时,让return的promise也失败
// )
//简洁写法
result.then(resolve , reject)
} else {
/*如果回调函数返回的不是promise,return的promise就会成功,value就是返回的值*/
resolve(result)
}
} catch (error) {
reject(error)
}
}
if (self.status === PENDING) {
//当前状态是pending状态,将回调函数保存起来
self.callbacks.push({
onResolved () {
handle(onResolved)
},
onRejected () {
handle(onRejected)
}
})
} else if (self.status === RESOLVED) { //如果当前是resolved状态,异步执行onResolved并改变return的promise状态
setTimeout(() => {
handle(onResolved)
})
} else { //如果当前是rejected状态,异步执行onRejected并改变return的promise状态
setTimeout(() => {
handle(onRejected)
})
}
})
}
//promise原型对象的catch():指定失败的回调函数,返回一个新的promise
Promise.prototype.catch = function (onRejected) {
return this.then(undefined , onRejected)
}
/**
* Promise函数方法
* resolve:返回一个指定结果的成功的promise
* reject:返回一个指定的reason的失败的promise
* all:返回一个promise,只有当所有promise都成功时才算成功,否则失败
* race:返回一个promise,其结果由第一个完成的promise决定
*/
Promise.resolve = function (value) {
//返回一个成功/失败的promise
return new Promise((resolve , reject) => {
// value是promise
if (value instanceof Promise) { //使用value的结果作为当前promise结果
value.then(resolve , reject)
} else {
// value不是promise
resolve(value)
}
})
}
Promise.reject = function (reason) {
// 返回一个失败的promise
return new Promise((resolve , reject) => {
reject(reason)
})
}
Promise.all = function (promises) {
//用来保存 所有成功value的数组
const values = new Array(promises.length)
//用来保存成功promise的数量
let resolveCount = 0
//返回一个新的promise
return new Promise((resolve , reject) => {
//遍历获取每个promise结果
promises.forEach((p , index) => {
Promise.resolve(p).then(
value => {
resolveCount++
//p成功,将成功的value保存到values中
values[index] = value
//如果全部成功,将return的promise改为成功
if (resolveCount === promises.length) {
resolve(values)
}
},
reason => { //只要有一个失败了,所有都失败
reject(reason)
}
)
})
})
}
Promise.race = function (promises) {
//返回一个新的promise
return new Promise((resolve, reject) => {
//遍历获取每个promise结果
promises.forEach((p , index) => {
Promise.resolve(p).then(
value => { //一旦有成功的,将return变为成功
resolve(value)
},
reason => { //只要有一个失败了,所有都失败
reject(reason)
}
)
})
})
}
/**
* 返回一个promise对象,在指定的时间后确定结果
*/
Promise.resolveDelay = function (value, time) {
//返回一个成功/失败的promise
return new Promise((resolve , reject) => {
setTimeout(() => {
// value是promise
if (value instanceof Promise) { //使用value的结果作为当前promise结果
value.then(resolve , reject)
} else {
// value不是promise
resolve(value)
}
},time)
})
}
/**
* 返回一个promise对象,在指定的时间之后失败
*/
Promise.rejectDelay = function (reason, time) {
// 返回一个失败的promise
return new Promise((resolve , reject) => {
setTimeout(() => {
reject(reason)
})
})
}
//向外暴露promise函数
window.Promise = Promise
})(window)
3、类版本
/**
* 自定义promise函数模块,使用ES5语法
*/
//IIFE
(function (window) {
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
class Promise {
constructor (excutor) {
//将当前promise对象保存起来
const self = this
self.status = PENDING //给promise对象指定status,初始值为pending
self.data = undefined // 给promise对象指定一个用于存储结果数据的属性
self.callbacks = [] // 每个元素结构:{ onResolved() {}, onRejected() {}}
function resolve (value) {
// 如果当前状态不是pending,直接结束
if (self.status !== PENDING) {
return
}
//将状态改为resolved
self.status = RESOLVED
//保存value数据
self.data = value
//如果有待执行的callbacks函数,立即异步执行回调函数onResolved
if (self.callbacks.length > 0) {
setTimeout(() => { //放入队列中执行所有成功的回调
self.callbacks.forEach((callbacksObj) => {
callbacksObj.onResolved(value)
})
})
}
}
function reject (reason) {
// 如果当前状态不是pending,直接结束
if (self.status !== PENDING) {
return
}
//将状态改为rejected
self.status = REJECTED
//保存reason数据
self.data = reason
//如果有待执行的callbacks函数,立即异步执行回调函数onRejected
if (self.callbacks.length > 0) {
setTimeout(() => { //放入队列中执行所有成功的回调
self.callbacks.forEach((callbacksObj) => {
callbacksObj.onRejected(reason)
})
})
}
}
//立即同步执行excutor
try {
excutor(resolve , reject)
}catch (error) { //如果执行器抛出异常,promise对象变为rejected
reject(error)
}
}
//promise原型对象的then():指定成功和失败的回调函数,返回一个新的promise对象
then (onResolved , onRejected) {
onResolved = typeof onResolved === 'function' ? onResolved : value => value //向后传递成功的value
//指定默认的失败回调(实现错误/异常穿透的关键步骤)
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason } //向后传递失败的reason
const self = this
//返回一个新的promise对象
return new Promise((resolve , reject) => {
//调用指定的回调函数处理,根据执行的结果改变return的promise状态
function handle (callback) {
try {
const result = callback(self.data)
if (result instanceof Promise) {
/*如果回调函数返回promise,return的promise结果就是这个promise的结果*/
// result.then(
// value => resolve(value), //当result成功时,让return的promise也成功
// reason => reject(reason) //当result失败时,让return的promise也失败
// )
//简洁写法
result.then(resolve , reject)
} else {
/*如果回调函数返回的不是promise,return的promise就会成功,value就是返回的值*/
resolve(result)
}
} catch (error) {
reject(error)
}
}
if (self.status === PENDING) {
//当前状态是pending状态,将回调函数保存起来
self.callbacks.push({
onResolved () {
handle(onResolved)
},
onRejected () {
handle(onRejected)
}
})
} else if (self.status === RESOLVED) { //如果当前是resolved状态,异步执行onResolved并改变return的promise状态
setTimeout(() => {
handle(onResolved)
})
} else { //如果当前是rejected状态,异步执行onRejected并改变return的promise状态
setTimeout(() => {
handle(onRejected)
})
}
})
}
//promise原型对象的catch():指定失败的回调函数,返回一个新的promise
catch (onRejected) {
return this.then(undefined , onRejected)
}
/**
* Promise函数方法
* resolve:返回一个指定结果的成功的promise
* reject:返回一个指定的reason的失败的promise
* all:返回一个promise,只有当所有promise都成功时才算成功,否则失败
* race:返回一个promise,其结果由第一个完成的promise决定
*/
static resolve = function (value) {
//返回一个成功/失败的promise
return new Promise((resolve , reject) => {
// value是promise
if (value instanceof Promise) { //使用value的结果作为当前promise结果
value.then(resolve , reject)
} else {
// value不是promise
resolve(value)
}
})
}
static reject = function (reason) {
// 返回一个失败的promise
return new Promise((resolve , reject) => {
reject(reason)
})
}
static all = function (promises) {
//用来保存 所有成功value的数组
const values = new Array(promises.length)
//用来保存成功promise的数量
let resolveCount = 0
//返回一个新的promise
return new Promise((resolve , reject) => {
//遍历获取每个promise结果
promises.forEach((p , index) => {
Promise.resolve(p).then(
value => {
resolveCount++
//p成功,将成功的value保存到values中
values[index] = value
//如果全部成功,将return的promise改为成功
if (resolveCount === promises.length) {
resolve(values)
}
},
reason => { //只要有一个失败了,所有都失败
reject(reason)
}
)
})
})
}
static race = function (promises) {
//返回一个新的promise
return new Promise((resolve, reject) => {
//遍历获取每个promise结果
promises.forEach((p , index) => {
Promise.resolve(p).then(
value => { //一旦有成功的,将return变为成功
resolve(value)
},
reason => { //只要有一个失败了,所有都失败
reject(reason)
}
)
})
})
}
/**
* 返回一个promise对象,在指定的时间后确定结果
*/
static resolveDelay = function (value, time) {
//返回一个成功/失败的promise
return new Promise((resolve , reject) => {
setTimeout(() => {
// value是promise
if (value instanceof Promise) { //使用value的结果作为当前promise结果
value.then(resolve , reject)
} else {
// value不是promise
resolve(value)
}
},time)
})
}
/**
* 返回一个promise对象,在指定的时间之后失败
*/
static rejectDelay = function (reason, time) {
// 返回一个失败的promise
return new Promise((resolve , reject) => {
setTimeout(() => {
reject(reason)
})
})
}
}
//向外暴露promise函数
window.Promise = Promise
})(window)
六、async和await
1、async 函数
函数的返回值为promise对象
promise对象的结果由async函数执行的返回值决定
2、await表达式
await右侧的表达式一般为promise对象,但也可以是其他值
如果表达式是promise对象,await返回的都是promise的成功值
如果表达式是其他值,直接将此值作为await返回值
3、注意
await必须写在async函数中,但async函数中可以没有await
如果await的promise失败了,就会抛出异常,需要通过try … catch来捕获处理
七、JS异步之宏队列与微队列
原理图:
说明:
1、JS中用来存储待执行回调函数的队列包含两个不同特定的队列
宏队列:用来保存待执行的宏任务(回调),比如:定时器回调/DOM事件回调/Ajax回调
微队列:用来保存待执行的微任务(回调),比如:promise的回调/mutationObserver()的回调
2、JS执行时会区别这两个队列
JS引擎首先必须执行所有的初始化同步代码
每次准备取出第一个宏任务执行前,都要将所有的微任务一个一个取出来执行 【先执行微队列任务,再执行宏队列任务】