很多時(shí)候作為一個(gè)ioser很羨慕人家用promise來(lái)控制異步執(zhí)行函數(shù)。
雖然說(shuō)有promiseKit這種神器 但是總歸希望能了解一下promise;
- 何謂promise
A Promise is a proxy for a value not necessarily known when the promise is created.
It allows you to associate handlers with an asynchronous action's eventual success value or failure reason.
This lets asynchronous methods return values like synchronous methods: instead of immediately returning the final value,
the asynchronous method returns a promise to supply the value at some point in the future.
======
pending: initial state, not fulfilled or rejected.
fulfilled: meaning that the operation completed successfully.
rejected: meaning that the operation failed.
這是https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise 的介紹。
- 作為iOS 開(kāi)發(fā)。興許對(duì)于promise使用場(chǎng)景有限,但是肯定遇到下面的情況
[nettool getData(^(id data){
// 我還要繼續(xù)請(qǐng)求根據(jù)這個(gè)data獲取的數(shù)據(jù)
[nettool getData(^(id data){
// 我還要繼續(xù)請(qǐng)求根據(jù)這個(gè)data獲取的數(shù)據(jù)
[nettool getData(^(id data){
// 我還要繼續(xù)請(qǐng)求根據(jù)這個(gè)data獲取的數(shù)據(jù)
[nettool getData(^(id data){
// 我還要繼續(xù)請(qǐng)求根據(jù)這個(gè)data獲取的數(shù)據(jù)
[nettool getData(^(id data){
// 我還要繼續(xù)請(qǐng)求根據(jù)這個(gè)data獲取的數(shù)據(jù)
。。。。
})
})
})
})]
是不是看著很惡心,這就是我們常說(shuō)的回調(diào)地獄。對(duì)于寫(xiě)的人來(lái)說(shuō)不覺(jué)得,但是對(duì)以后某位同事來(lái)幫你查bug的時(shí)候,我想他會(huì)買(mǎi)一把刀吧。
試想一下 如果我們這么寫(xiě)呢?
[QXPromise promise^(Fullfilled fullfilled,Rejected rejected ){
[nettool getData(^(id data){
resolve(data)
// if error
rejected(err)
})]
}].then(^id(id data){
[nettool getData(^(id data){
resolve(data)
})]
}).then(^id(id data){
[nettool getData(^(id data){
resolve(data)
})]
}).then(^id(id data){
[nettool getData(^(id data){
resolve(data)
})]
});
是否覺(jué)得眼前一亮呢?
在這里我將會(huì)實(shí)現(xiàn)這個(gè)promise
- 定義promise的三個(gè)狀態(tài)
/**
promise狀態(tài)
- QXPromiseStatePending: 執(zhí)行中
- QXPromiseStateResolved: 完成執(zhí)行
- QXPromiseStateRejected: 已拒絕執(zhí)行
*/
typedef NS_ENUM(NSUInteger, QXPromiseState) {
QXPromiseStatePending = 0,
QXPromiseStateFullfilled = 1,
QXPromiseStateRejected = 2
};
定義block
typedef id (^QXRunBlock) (id value);
typedef void(^QXFullFilledHandler)(id value);
typedef void(^QXErrorBlock)(NSError *error);
typedef QXErrorBlock RejectHandler;
typedef void(^QXPromiseBlock)(ResolveHandler resolve,RejectHandler reject);
typedef void(^ProgressHandler)(double proportion,id value);
實(shí)現(xiàn)類(lèi)
@interface QXPromise : NSObject
@property(nonatomic) id value;
@property(nonatomic) NSError *error;
@property(nonatomic, copy) QXFullFilledHandler resolveBlock;
@property(nonatomic, copy) RejectHandler rejectBlock;
@property(nonatomic, copy) QXPromiseBlock promiseBlock;
@property(nonatomic, copy) RejectHandler catchBlock;
@property(nonatomic, copy) QXRunBlock thenBlock;
+ (QXPromise *)promise:(QXPromiseBlock)block;
我們開(kāi)始進(jìn)行梳理
初始化一個(gè)promise
- (instancetype)init:(QXPromiseBlock)initBlock {
self = [super init];
if (self) {
[self configure];
self.promiseBlock = initBlock;
}
self.promiseBlock(self.fullfilledblock,self.rejectedblock)
return self;
}
- (void)configure {
if (self) {
self.state = QXPromiseStatePending;
[self keepAlive];
__weak QXPromise * wSelf = self;
self.fullfilledblock = ^(id value){
__strong QXPromise *sSelf = wSelf;
if (sSelf.state != QXPromiseStatePending) return;
if ([value isKindOfClass:[QXPromise class]]) {
if(((QXPromise *)value).state == QXPromiseStatePending) {
sSelf.nextPromise = value;
}
[(QXPromise *) value addObserver:sSelf forKeyPath:@"state" options:NSKeyValueObservingOptionNew context:nil];
} else {
sSelf.value = value;
sSelf.state = QXPromiseStateFullfilled;
[sSelf loseControl];
}
};
self.rejectBlock = ^(NSError *error){
__strong QXPromise *sSelf = wSelf;
if (sSelf.state != QXPromiseStatePending) return;
sSelf.error = error;
sSelf.state = QXPromiseStateRejected;
};
}
}
我們初始化了這個(gè)promise。同時(shí)對(duì)fullfilled和reject 兩個(gè)blokc初始化。隨后將會(huì)執(zhí)行這個(gè)promiseblock;
劃重點(diǎn)的來(lái)了##
先看我們的fullfilledblock
- 確定返回參數(shù)的類(lèi)型,如果是promise說(shuō)明還有鏈需要調(diào)用,
- 若是value 說(shuō)明是返回值該promse也屬于調(diào)用結(jié)束了。進(jìn)入fullfilled狀態(tài),
- 是promise對(duì)象的 應(yīng)該對(duì)其進(jìn)行監(jiān)聽(tīng)。這里使用了kvo。
4.fullfilled綁定的value會(huì)被這個(gè)promise持有。這對(duì)后面的操作來(lái)說(shuō)很重要。
來(lái)看我們的rejectblock
。。。沒(méi)啥看的。拋出錯(cuò)誤 ?
kvo部分應(yīng)該屬于改promise的核心所在了
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
if ([keyPath isEqualToString:@"state"]) {
QXPromiseState newSate = [change[NSKeyValueChangeNewKey] unsignedIntegerValue];
if (newSate == QXPromiseStateRejected) {
[object removeObserver:self forKeyPath:@"state"];
if (self.catchBlock) {
self.catchBlock([(QXPromise *) object error]);
self.fullfilledBlock(nil);
} else {
self.rejectBlock([(QXPromise *) object error]);
}
} else if (newSate == QXPromiseStateFullfilled) {
[object removeObserver:self forKeyPath:@"state"];
@try {
id value = nil;
self.valueKeptForRetry = [(QXPromise *)object value];
if (self.thenBlock) {
value = self.thenBlock([(QXPromise *) object value]);
} else {
value = [(QXPromise *) object value];
}
self.thenBlock = nil;
self.fullfilledBlock(value);
} @catch (NSException *exception) {
self.rejectBlock(exception);
} @finally {
}
}
}
}
kvo中會(huì)拋出錯(cuò)誤,或者判斷是否需要繼續(xù)執(zhí)行。
是否執(zhí)行通過(guò)thenblock來(lái)做,這個(gè)地方一會(huì)再說(shuō)。
取到thenblock的返回值 作為下一個(gè)fullfilledBlock的參數(shù)繼續(xù)執(zhí)行。
then
- (QXPromise *(^)(QXRunBlock))then {
__weak QXPromise * wSelf = self;
return ^QXPromise*(QXRunBlock thenBlock){
__weak QXPromise *newPromise = nil;
newPromise = [QXPromise promise:^(fullfilledHandler fullfilled, RejectHandler reject) {
__strong QXPromise *sSelf = wSelf;
resolve(sSelf);
}];
newPromise.thenBlock = thenBlock;
return newPromise;
};
嗯 。。。沒(méi)了 有時(shí)間會(huì)寫(xiě)另外一種promise的實(shí)現(xiàn)方式。
項(xiàng)目使用還是挺好玩的。
當(dāng)然還有其他的拓展功能 all catch finally....