先简介下Promise吧
Promise为什么会出现
这得说到Web前端的开发,异步编程为js带来强大灵活性,但它也带来两个问题,多层嵌套令代码可读性变差以及无法满足并行逻辑的穿行执行,然后机智的程序员们构架出Promise这样的一个链式回调机制,它类似于一个事务管理器,它的作用就是将各种内嵌回调的事务用流水形式表达。
那关我们写iOS什么事呢?— 方便呗。
Promise 基础
Promise 有三种状态,分别是
- Pending(进行中)
- Resolved(已完成,又称 Fulfilled)
- Rejected(已失败)
Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。一旦状态改变,就不会再变,任何时候都可以得到这个结果。这是与事件(Event)完全不同。Event是一旦错过,就真的错过了。
Promise 的三个属性
- value 存储成功/失败的结果值
- steps 是一个可变数组,链式存储处理函数
- state 对象的状态
Promise的两个方法
- then
- catch
Promise 的常规使用方法
var promise = new Promise(function(fulfiller, rejecter) {
var promise = new promise(){self.steps=[];}
if (/* 异步操作成功 */){
promise.value = result;
fulfiller(value);
} else {
promise.value = error;
rejecter(error);
}
});
---promise 内部
function testBlockC(blockFunction){
// do something
}
Promise
构造函数接受一个函数作为参数,该函数的两个参数分别是 fulfiller
方法和 rejecter
方法。
如果异步操作成功,则用 fulfiller
方法将 Promise 对象的状态,从「未完成」变为「成功」(即从 pending 变为 resolved);
如果异步操作失败,则用 rejecter
方法将 Promise 对象的状态,从「未完成」变为「失败」(即从 pending 变为 rejected)。
再简单说说Promise细节问题
Promise
对象代表的是一个任务未来的执行结果。
使用then
来获得 Promise
对象的value。
当 Promise
代表的的异步操作任务成功完成的时候,之前我们传递给then
方法的block就会被执行,并且它就将会携带Promise
执行完成时得到的结果值。Promise
是支持链式调用的,它的构造函数、then
方法、catch
方法都是返回的Promise
对象,一旦Promise
对象被返回,你就可以立刻调用相关的then
或者catch
方法,以此往复,高产高效。
then
很好的诠释了Promise模式。提供给 then
方法的block方法可能没有参数,也可能持有若干个参数(例如通过注册onFulfill(成功回调)、onReject(失败回调)、onProgres(进度回调)来与promise交互,而这些回调参数的个数是可以根据自己需求可选的。),而它的返回值应该是不多于一个对象。因此我们使用id
作为then的方法信号量,这样你就可以自己适配block的方法而不用受限了。
then
函数返回一个promise对象(称为promise2,前者称为promise1),promise2受promise1状态的影响。
Promise
的执行时机是在它的block传递给它的 then
方法后。
如果一个你的block内部抛出一个异常(exception),或者你返回一个NSError对象,那么下一个Promise
将会终止执行,而当前Promise
的catch
就会被调用,这样就保证了链式执行异步操作的统一性。
catch
方法的使用方式与then
类似,只是目的不同而已。
值得注意的是,then
、catch
永远都执行在main队列上。
另外还有一点,由于catch
是一个C++的关键词,因此,catch方法不能用于obj-C混编C++的文件里,如果非要那样写,应该自己实现一个别的名字命名的方法,比如catchOn。
Promise先创建,定义好rejecter和fulfiller回调方法,里面包裹resolve方法。
执行then方法的时候返回了一个promise指针的handlerblock,通过这个handlerblock对内对外提供了一个参数接口。执行then的时候,先判断promise的value是不是promise类型,如果是,就对其继续执行then操作,如果self.value不是promise类型而是别的什么类型的值,就将其包裹成一个promise继续执行then操作,总之目的就是通过then方法要获得叶子节点(value=nil),然后将叶子节点按照带参数的handlerblock的形式返回,这个handlerblock的作用是,如果handlerblock的参数不为空,且self.value的叶子节点不是NSError类型,就将这个节点添加到self.steps数组里面,然后执行ZHPromiseSafeCall方法。
ZHPromiseSafeCall的作用是,将promise和上一步通过handlerblock传入的参数绑定起来。通过将handlerblock强制转换成NSMethodSignature信号类型的方法,获得其类型methodReturnType[0]。如果signature.numberOfArguments == 1,那就说明第一个argument就是这个block本身,如果>1,则下标1以后的数据都是传入的block的参数值。此外,如果signature.methodReturnType[0] = ‘v’,那么传入的promise就是代表根节点,否则则为中间节点,中加节点要将block赋值给promise.value.