你不知道的javascript读书笔记(promise)

597 阅读4分钟

Promise

控制反转:
将回调函数交付给第三方执行,导致失去控制权
信任问题
控制反转带来的弊端问题,执行的回调函数可能导致一些问题

promise产生:
希望既能得到第三方任务何时结束的能力,又能自己执行回调函数,自己决定下一步该如何运作

未来值

未来值的重要特性:
时间可能失败或者成功

完成事件

假定执行一个任务,那么这个函数可能是立即完成也可能是需要一段时间才能完成。
我们需要知道的是这个函数什么时候结束,这样我们就可以进行下一个任务了。
因此我们需要实现监听,而监听执行结果的函数又两个,就是resolve和reject,这两个都是回调函数,resolve用于监听成功的结果(成功后执行),而reject则是失败,这就是resolve和reject的由来(知其所以然)

具有then方法的鸭子类型

鸭子类型:
看起来像鸭子,叫起来也像鸭子,那它就是鸭子

promise的检测标准是判断其是否具有then方法

所以下面两种情况值得讨论:

  1. var o = {then:function(){}};
    var v = Object.creat(o);
    那么v也是被判断为promise

  2. Object.prototype.then = function(){};
    Array.prototype.then = function(){};
    那么随意创建的数组或对象都具有then方法,他们都是鸭子

回调调用次数过多问题

在promise多次调用resolve()或者reject(),结果是执行第一个被执行的回调函数后,其他的都会忽略,因为每个回调函数都有return,所以会跳出函数

链式流

链式流的关键:

  1. 每次对promise调用then方法时,then末会返回一个新的promise(与jq链式操作有点类似)
  2. 每次执行的结果(返回值)必然可以传入下一个promise中

如果在链式操作中(多个then方法),如果其中的一个任务出错了,那么它永远不会走到下级的then方法中,除非它的错误被捕获(监听任务失败的reject)。这个捕获的动作在某种程度上相当于在这一位置将将整天链“重置”回到了正常的工作状态

错误处理

在链式流中,错误是怎么走向一个又一个新promise的呢?
原因就是会又一个默认拒绝护理函数会被定义。
而默认拒绝函数只是把错误重新在新的一个promise中抛出,使得新的promise以同样的方式给拒绝,直到显式定义的拒绝处理函数位置,才能返回正常的工作状态。

promise模式

promise.all:
等待两个或者多个并行/并发的任务都完成才能继续,完成的顺序并不重要,但是必须全部完成,门才能打开并让流程控制继续。
promise.all([])接受一个数组参数,里面的元素是n个promise(通常是promise),当所有的promise执行完毕的时候才能继续走向下一步(不管执行的顺序)
如果其中一个任务被拒绝,那么主promise.call()也会被拒绝,并丢弃来自其他所有promise的全部结果


promise.race():
与promise.all()接受一个传入n个promise的数组,一旦又某个promise率先完成,promise.race()也就完成了。一旦有个拒绝的,整个也就拒绝了

new Promise()构造器

promise.reject()
let p1 = new Promise(function(resolve,reject){
    reject("Oops");
})
let p2 = Promise.reject("Oops");

p1等效于p2
promise.resolve()

常构建一个已完成的promise,执行的参数可能是完成的也可能是拒绝的 具体就看传入的元素(鸭子模型)的状态(最终决议值)

then

then()接受两个参数,一个用于完成回调,一个用于拒绝回调。
如果其中一个回调被省略掉或者传入非函数参数,那么就会转化成对应的默认回调;
默认完成回调就是上述的完成回调被省略掉或者非函数,它负责把消息传递下去
默认拒绝回调也就是上述的默认拒绝函数,把错误抛出到下一个promise中直到显式拒绝函数定义

catch

catch()只接受一个拒绝回调作为参数化,并自动替换成默认完成函数

promise.then(null,rejected);
promise.catch(rejected);
上面两者是等效的,而且两者都会创建一个带又决议值的新promise

Promise的局限性

顺序错误处理

一个promise链只是连接到一起的成员,并不是一个整体;即会有外部方法能够观察可能发生的错误。

单一值

promise只能有一个完成值或者一个拒绝理由

惯性

在一个充满回调函数的代码块中,现存的代码不识别promise,那么还是保存原来的样子要好

无法取消的promise

一旦创建一个promise并注册完成或拒绝处理函数,这时如果某种情况发生导致这个任务得不到处理,实际上是没有办法从外部停止这个进程的