You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
constasyncDoing=function(){returnnewPromise(function(resolve,reject){// 下面一行会报错,因为i没有声明resolve(i===5);});};asyncDoing().then(function(){console.log('have Done');});setTimeout(()=>{console.log(111)},5000);// 控制台最终输出// Uncaught (in promise) ReferenceError: i is not defined// 111
前言
基本上面试问Promise首先会问你很简单的一句,“你了解过Promise吗”
这是时候只要你把我下面“是什么”的说明理解好了就足够了。但是假设面试官追问下去,你要对他的一些方法要有理解。
是什么
Promise是解决异步编程的一种方案。以前我们处理异步操作,一般都是通过回调函数来处理,典型的例子就好像使用
setTimeout
一样,如果执行操作函数里面还有setTimeout
,一层一层往下,都有的话。那么代码看起来十分臃肿,不利于维护,也很容易写出bug。而Promise的出现,能够让异步编程变得更加可观,把异步操作按照同步操作的流程表达出来,避免层层嵌套的回调函数。
Promise对象有三种状态,进行中
pending
、完成成功fulfilled
、失败rejected
,顾名思义,表示这个异步操作是进行中还是成功还是失败了。Promise的状态一旦确定了,就不会再更改了,这就是promise(承诺)的由来吧,承诺状态确定了就是确定了。
然而Promise还是有不足的地方:
setTimeout
那样,我还可以使用clearTimeout
取消掉。创建
promise是一种对象类型,即可通过
new Promise()
来创建一个promise实例对象。参数是一个函数,这个函数带有两个参数,两个参数都是函数类型,调用
resolve
方法,表示异步操作完成成功了;调用reject
方法,表示异步操作失败了。调用这两个方法,会返回一个新的Promise对象,而这个Promise对象的最终状态才是这个异步操作的最终状态。具体规则会在下面的
resolve
和reject
章节说明在创建
Promise
对象时,参数的函数内的同步脚本会立即执行,如实际上上述的
console.log('Promise');
是同步脚本,resolve
了之后的then
方法是异步脚本。要注意,执行了
resolve
或reject
方法后,并不会终止异步函数往下执行假设上述例子条件判断为
true
,则执行了resolve
之后,还会执行console.log
。一般执行
resolve
或reject
都是宣告异步操作这个函数本身完结了,其余还需要进一步的操作应该放在外部再处理(如下述说的在then
里处理),所以我们一般是使用return
宣告此部分动作完结这样就执行不到
console.log
了。常用方法
then
then是promise的实例方法,接受两个参数,类型是函数。
fn1
是表示该promise
状态为成功时,需要进行的下一步操作,即被resolve
了,fn1
函数带有一个参数,这个参数就是promise
里执行resolve(result)
传的参数result。fn2
是可选的,表示该promise
状态为失败时,需要进行的下一步操作,即被reject
了,fn2
函数带有一个参数,这个参数就是promise
里执行reject(result)
传的参数result,或者脚本抛出的错误信息。例子
上述例子如果xxx结果为true,则会输出“异步操作完成”,false的话输出“异步操作失败”。
then
方法放回的是一个新的Promise
实例,因此后面还可以接着then
,因此可以采用链式写法如果返回的还是一个
Promise
对象(即有异步操作),那么后面的then
是要等前面的异步操作完成了才会执行。如果你跟上面那几句话有点混乱的话,这么理解下:
catch
Promise的实例方法。
catch
方法实际上是then的一种特殊形式。用来捕获它前面的异步操作抛出的错误。即异步操作的失败时就可以调用该方法做进一步操作。即无视了异步操作成功时的情况,执行失败时的情况。上述then中的例子可以改为以下形式:
相当于
但是我们要注意,虽然
catch
方法和then
里的第二个参数方法都是用来对异步操作失败时做进一步处理,但是他们还是有区别的。前者是能把链式结构中的“上游”部分中只要有抛出错误,就能捕获到,执行catch
。而后者仅仅能捕获到它本次异步操作的失败。上述例子中,
catch
能把前面的promise操作以及前两个then操作中的错误给捕获到。而例子中的fn2函数,只能捕获到第一个then里执行错误的情况因此我们建议,使用catch替换用then的第二个参数来捕获错误,而且书写格式也比较直观。
吃掉错误
如果不使用
catch
捕获Promise
操作抛出的错误,那么就算报错了也不会影响到外部代码,不会退出进程、终止脚本。先是浏览器抛出i未定义的错误,后面就打印出111
我们之前的认识是,在同步脚本里,如果某个脚本出错了,会终止下面的脚本继续执行,但是这里并不会
catch
方法也是返回一个Promise
对象,如果后面接着一个then
方法,那么catch
前的Promise
对象如果没有抛出错误,那么会跳过catch
,然后执行then
,如果有错,那么先执行catch
再执行then
finally
Promise的实例方法。上面我们说到用then来处理异步成功,用catch处理失败,那么如果我们并不在乎他们是否成功失败,都要在之后执行某个操作,就可以是用
final
方法了。用法跟上面的很相似。all
类方法。当你有好几个异步操作,你想等他们都执行完了之后再执行某个操作,那么就要用到
all
方法了。参数数组里面的每个元素都是Promise对象,如果原本不是的,会使用下面说到的
Promise.resolve
进行转化。参数是的形式不局限于数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。返回的状态的情况:
then
里的函数,res
是一个数组,里面的元素按照all
参数里的promise的顺序一一对应它们各自的resolve
值catch
,e
为对应的错误信息。Promise
实例本身有使用catch
捕获错误,那么对于all
来讲,是返回了fullfilled
状态的race
类方法。如有一批异步操作,你只想当它们之中有一个事先结束了就执行某个操作,就可以使用它。
参数跟
all
方法一样。如果
promise2
是第一个异步执行完的,那么就以它的状态为最终状态。resolve
类方法。执行该方法返回一个
Promise
对象等价于
关于返回的
Promise
的状态按照如下规则:param
如果是一个promise
对象,则原封不动地原样返回这个promise
对象promise
对象,但是对它已经有了如then
或catch
的操作,上面我们也说过这两个方法还是可能会返回Promise
对象,所以会以这个最终状态的Promise
对象返回。其实也就是上一个规则的特性情况而已Promise
对象以上规则同样是使用在
Promise
对象中的resolve
方法reject
类方法。执行该方法返回一个
Promise
对象关于返回的
Promise
的状态规则很简单,与上述的resolve
是不同的param
如果是Promise
对象,那么原样返回,尽管它可能本身还有then
或catch
操作,也不管。这就是不同之处Promise
对象以上规则同样是使用在
Promise
对象中的reject
方法The text was updated successfully, but these errors were encountered: