基於ObjC的輕量級Promise庫——RWPromiseKit

canopus4u發表於2016-03-21

閒來無事。在看JavaScript的時候發現Promise這東西不錯。將隱藏在非同步呼叫中的邏輯變成了同步呼叫。

getJSON("/posts.json").then(function(posts) {
  // ...
  consume(posts);
}).catch(function(error) {
  console.log(`something wrong!`, error);
});

關於Promise,可以看這裡這裡

github上搜了一下有一個Star比較多的。大致瀏覽了一下,mxcl/PromiseKit主要是靠RunLoop的實現的(也有用OperationQueue實現的)。

實現

構思了一下,通過ARC+KVO完全可以實現promise之間依賴關係。至於鏈式呼叫,在我的另一篇文章中有介紹了,不在此贅述了。

程式碼放在我的github上了。歡迎拍磚。

功能

Promise

構造一個promise:

RWPromise* p1 = [RWPromise promise:^(ResolveHandler resolve, RejectHandler reject) {
                    if (condition){
                        resolve(@"result");
                    }else{
                        reject(@"result");
                    }
                }];

resolvereject用於改變promise的狀態,由promise生成者來決定。呼叫resolvereject可以同步或者非同步。

then 和 catch

  • then
    then本身會返回一個新的promise。新的promise會依賴於上一個promise的狀態。

當promise的狀態在變成Resolved之後會呼叫then傳入的block。前一個promise中resolve的value會傳遞給then產生的promise。
then的block中必須返回一個值,若返回值不是RWPromise,則等價於呼叫reslove(value)

這裡我對then做了一些改造,只傳了resolved的handler。並沒有傳入rejected的handler。

  • catch
    catch本身也會返回一個新的promise。新的promise會依賴於promise鏈上所有promise的狀態。若某個promise的狀態為rejected,則會呼叫整個鏈上上的第一個catch的promise。

看如下程式碼:

[RWPromise promise:^(ResolveHandler resolve, RejectHandler reject) {
                    resolve(@"1");
                }].then(^id(id value){
                    NSLog(value);
                    return @"2";
                }).catch(^(NSError* e){
                    NSLog(@"error");
                }).then(^id(id value){
                    NSLog(value);
                    return nil;
                });

最後結果為:

1
2

[RWPromise promise:^(ResolveHandler resolve, RejectHandler reject) {
                    reject(nil);
                }].then(^id(id value){
                    NSLog(value);
                    return @"2";
                }).catch(^(NSError* e){
                    NSLog(@"error");
                }).then(^id(id value){
                    NSLog(value);
                    return nil;
                });

結果為:

error
<nil>

上面參考的連結有詳細的解釋,不多說了,具體參見javascript。目前支援的API:
then
catch
finally
after
retry
timeout
map
filter
reduce
race
all
resolve
reject

  • 存在的問題

  1. Block支援多引數

原作寫於segmentfault 連結

相關文章