1、准备知识
1、回调函数:
理解:一个函数,自己定义的,自己没有调用,但是函数执行了。
同步回调:立即执行,完全执行完才结束,不会放到回调队列中
例子: 数组遍历的forEach()还有promise的excutor
异步回调:不会被立即执行,会被放到回调函数中将来执行
例子:定时器回调、ajax回调、promise的成功回调onResolve和失败回调onReject
2、错误类型
*Error:所有错误的父类型
ReferenceError:引用变量不存在,打印一个未声明的变量会触发此错误
TypeError:数据类型不正确,将一个一般类型的变量当成函数调用会触发此错误
RangerError:数据值不在允许的方范围,一个递归没有跳出条件,递归会不断执行最后将栈占满
SyntaxError:语法错误
*错误处理
捕获错误:try...catch() 使代码不会因为报错而停止执行
抛出错误:throw error 抛出的错误可以用try...catch()来接收
2、Promise
1、promise是什么:
promise是js中进行异步编程的新的解决方案
具体表达:
从语法上来说:promise是一个构造函数
从功能上说:promise对象用来封装一个异步操作并可以获取其结果
2、promise状态:
pedding:初始状态
resolve:成功状态
reject:失败状态
3、promise状态的改变:
pending变为resolved
pending变为rejected
说明 : 只有这两种,且一个promise对象只能改变一次
无论成功还是失败,都只会由一个数据结果
成功的结果数据一般称为value,失败的结果一般成为reason
4、promise包含的内容:
promise构造函数:Promise(excutor{})
excutor函数:同步执行(resolve,reject)=>{}
resolve函数:内部定义成功时我们调用的函数 value=>{}
reject函数:内部定义失败时我们调用的函数 reason=>{}
说明:excutor会在promise内部立即同步回调,异步操作在执行器中执行
4、promise的基本使用:
Promise是一个构造函数,构造函数的参数是一个函数即excutor(同步函数),该函数用来修改promise的状态可以是pedding->resolve成功,pedding->reject失败。然后可以执行.then()函数用来处理成功或者失败的回调
5、promise的好处
1、指定回调函数的方式更加灵活:
旧的:必须在启动异步任务前指定
promise: 启动异步任务==>返回promise对象=>给psomise对象绑定回调函数(甚至可以在异步任务执行结束后指定)
2、支持链式调用 可以很好地解决回调地狱问题
什么是回调地狱:回调函数的嵌套调用,外部回调函数异步执行的结果是嵌套回调函数执行的条件
回调地狱的缺点:不便于阅读/不便于异步处理
6、Promise的基本方法
1、promise.prototype.then方法:(onResolved,onRejected)=>{}
onResolved函数:成功的回调函数(value)=>{}
onRjected函数:失败的回调函数(reason)=>{}
说明:指定用于得到成功的value的成功回调和用于得到失败的reason的失败回调
返回一个新的promise对象
2、promise.prototype.catch方法:(onRejected)=>{}
onRejected函数:失败的回调函数(reason)=>{}
说明:相当于then(undefined,onRejected)
3、promise.resolve方法:(value)=>{}
value:成功的数据或promise对象
说明:返回一个成功/失败的promise对象
4、promise.reject方法:(reason)=>{}
value:失败的原因
说明:返回失败的promise对象
5、promise.all()方法:(promises)=>{}
promises:包含n个promise的数组
说明:返回一个新的promise,只有所有的Prmise成功才成功,只要有一个失败就直接失败
6、promise.race()方法:(promises)=>{}
promises:包含n个promise的数组
说明:返回一个新的promise,第一个完成promise的结果状态就是最终的结果
6、自定义promise之前的几个关键问题
1、promise的状态如何改变
resolve(value):如果当前是pedding就会变成resolve
reject(reason):如果当前是pedding那么就会变成reject
抛出异常:如果当前是pedding就会变为reject
2、改变promise状态和指定回调函数谁先谁后
(1)都有可能,正常情况下是先指定回调函数在改变状态,但是可以先改变状态在指定回调
(2)如何先改变状态在指定回调
在执行器中调用resolve()/reject()
延迟更长时间再调用then()
(3)什么时候才能得到数据
如果先指定回调函数,那么在状态方法改变时,回调函数就会调用,得到数据
如果先改变状态,那么当指定回调时,回调函数就会调用,得到数据
3、关于promise的then方法返回promise对象的状态
promise.then()返回的新promise的结果状态由什么决定?
(1)简单表达:由then()指定的回调函数执行的结果决定
(2)详细表达:
*如果抛出异常:新的promise变为rejected,reason为抛出的异常
*如果返回的是一个非promise的任意值,新promise变为resolved,value为返回的值,如果没有返回结果那么相当于return undefined
*如果返回的是另一个新的promise,此时promise的结果就会成为新的promise的结果
4、promise如何进行串联的多个任务操作
(1)promise的then()返回一个新的promise,可以实现then的链式调用
(2)通过then的链式调用串联多个同步/异步任务
5、promise异常穿透
(1)当使用promise的then链式调用时,可以在最后面指定失败的回调
(2)前面任何操作出了异常,都会传到最后失败的回调中去
中断promise链
(1)当使用promise的then链式调用时,在中间中断,不在调用后面的回调函数
(2)办法:在回调函数中返回一个pendding状态的promise对象
7、自定义的promise
1、promsie是一个构造函数并且接受一个函数(excutor)作为参数,这个函数是同步执行的,该函数又接收两个函数作为参数resolve(),reject()。代码实现:
2、一个promise应该有的数据:状态(pedding,resolve,reject),传递的数据,用于存储then中的回调函数的数组。为什么要设置这个数组,因为我们前面讨论过promise修改状态和指定回调函数顺序的问题(问题2),如果先指定回调函数在修改状态那么此时应该将回调函数存储起来,以便修改过状态之后直接调用。代码实现:
3、resolve和reject函数所做的工作:修改状态(只修改一次),将传递的数据保存,如果回调函数已经指定那么执行回调函数。代码实现:
4、如果promise抛出一个错误那么他将会执行reject函数,即问题1的第三点,代码实现:
5、then函数执行以下几种情况需要考虑:状态是否已经发生改变,如果改变直接执行onResolved函数,如果没有改变那么将onResolved函数和onRejected函数压入callback数组中,代码实现:
6、关于promise的then方法返回promise对象的状态即问题3,如果回调函数返回是promise,那么return的那个promise结果就是要向下传递的结果。这种情况在原装的promise中是以return new promise.resolve(value)的形态呈现。
要想知道返回的是否成功必须取回promise的值,因此用then的方法来获取promise的值以及状态
如果成功说明原装代码为return new promise.resolve(value),返回的下一个状态也应该是成功,所以调用resolve
如果失败说明原装代码为return new promise.reject(reason),返回的下一个状态也应该是失败,所以调用reject
实现代码:
7、如果then函数中不指定onResolved函数,onRejected函数时,promise有默认的操作,如果是不指定onResolved函数,那么把上面的value值继续向下传递,如果不指定onRejected函数那么抛出一个错误。代码实现:
完整代码:https://github.com/wangczc1234/Promise
最后欢迎大家投递
字节跳动校招内推码: 2XVEJNC
校招投递链接: https://jobs.toutiao.com/s/djchQRf
社招投递链接: https://job.toutiao.com/s/djc2b4C