Promise
控制反转:
将回调函数交付给第三方执行,导致失去控制权
信任问题:
控制反转带来的弊端问题,执行的回调函数可能导致一些问题
promise产生:
希望既能得到第三方任务何时结束的能力,又能自己执行回调函数,自己决定下一步该如何运作
未来值
未来值的重要特性:
时间可能失败或者成功
完成事件
假定执行一个任务,那么这个函数可能是立即完成也可能是需要一段时间才能完成。
我们需要知道的是这个函数什么时候结束,这样我们就可以进行下一个任务了。
因此我们需要实现监听,而监听执行结果的函数又两个,就是resolve和reject,这两个都是回调函数,resolve用于监听成功的结果(成功后执行),而reject则是失败,这就是resolve和reject的由来(知其所以然)
具有then方法的鸭子类型
鸭子类型:
看起来像鸭子,叫起来也像鸭子,那它就是鸭子
promise的检测标准是判断其是否具有then方法
所以下面两种情况值得讨论:
-
var o = {then:function(){}};
var v = Object.creat(o);
那么v也是被判断为promise -
Object.prototype.then = function(){};
Array.prototype.then = function(){};
那么随意创建的数组或对象都具有then方法,他们都是鸭子
回调调用次数过多问题
在promise多次调用resolve()或者reject(),结果是执行第一个被执行的回调函数后,其他的都会忽略,因为每个回调函数都有return,所以会跳出函数
链式流
链式流的关键:
- 每次对promise调用then方法时,then末会返回一个新的promise(与jq链式操作有点类似)
- 每次执行的结果(返回值)必然可以传入下一个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并注册完成或拒绝处理函数,这时如果某种情况发生导致这个任务得不到处理,实际上是没有办法从外部停止这个进程的