PromiseKit與RxSwift的是是非非

前言

在之前的文章Moya+PromiseKit+RxSwift優(yōu)雅的書寫網(wǎng)絡(luò)請求中,我們嘗試了使用PromiseKit和RxSwift共同實現(xiàn)網(wǎng)絡(luò)請求,在后來我個人的嘗試中發(fā)現(xiàn)了問題校镐,遂撰文記之。

問題描述

PromiseKit的閉包只會執(zhí)行一次捺典。

環(huán)境配置

  • Xcode 8.3
  • Swift 3

實例

這一切都是由于實現(xiàn)一個帶有緩存的網(wǎng)絡(luò)請求引起的鸟廓。為此我們實現(xiàn)一個RxMoyaProvider的Extension,用于實現(xiàn)帶有緩存的網(wǎng)絡(luò)請求襟己。

extension RxMoyaProvider {
    
    func offLineCacheRequest(_ token: Target) -> Observable<Response> {
        return Observable.create({[weak self] (observer) -> Disposable in
            // 1. 在這里我們讀取本地緩存中的數(shù)據(jù)引谜,若有緩存,則返回緩存數(shù)據(jù)
            // 偽代碼
            if 存在緩存 {
                observer.onNext(緩存數(shù)據(jù))
            }
            
            //2 .進(jìn)行正常的網(wǎng)絡(luò)請求
            let cancellableToken = self?.request(token) { result in
                switch result {
                case let .success(response):
                    // 3. 返回請求后的最新數(shù)據(jù)
                    observer.onNext(response)
                    observer.onCompleted()
                    // 4. 緩存并覆蓋舊數(shù)據(jù)
                    // 偽代碼
                    緩存數(shù)據(jù)
                        
                case let .failure(error):
                    observer.onError(error)
                }
                
            }
            return Disposables.create {
                cancellableToken?.cancel()
            }
            
        })
        
    }
}

我們基于剛剛實現(xiàn)的這個拓展再實現(xiàn)一個網(wǎng)絡(luò)請求。注意此處成功的回調(diào)result

func getHomepagePageDataWithCache() -> Promise<HomepageData>  {
        return Promise(resolvers: { (result, error) in
            provider.offLineCacheRequest(.frontpage)
                    .distinctUntilChanged()
                    .filterSuccessfulStatusCodes()
                    .mapJSON()
                    .mapObject(type: HomepageData.self)
                    .subscribe(onNext: {
                        result($0) //此處為PromiseKit的成功回調(diào)
                    }, onError: {
                        error($0)
                    })
                    .addDisposableTo(disposeBag)
        })
    }


然鵝就在這里出現(xiàn)問題了某筐,當(dāng)我們調(diào)用這個方法時:

viewModel.getHomepagePageDataWithCache().then {
            print($0.packages?.last?.head ?? "")
        }.catch {
            print($0)
        }

第一次調(diào)用因為本地沒有緩存溃槐,所以打印print($0.packages?.last?.head ?? "")只會調(diào)用一次,然鵝再次運行哮幢,存在本地緩存的情況下,該打印語句依然只執(zhí)行一次。
經(jīng)過打斷點滑频,我發(fā)現(xiàn)相關(guān)代碼均已經(jīng)執(zhí)行:

// 請求成功前
if 存在緩存 {
    observer.onNext(緩存數(shù)據(jù))  
}

// 請求成功后
    observer.onNext(response)

以上兩次 observer.onNext都觸發(fā)了RxSwift訂閱,斷點也會停留在訂閱里面PromiseKit的閉包result上:

.subscribe(onNext: {
                        result($0)
                    },

但是在最終的閉包里只執(zhí)行了一次打用2亍:

then {
            print($0.packages?.last?.head ?? "")
        }.

原因

經(jīng)過查詢資料误趴,原因如下:

PromiseKit 不具備流的特性,即不支持依賴時間順序依次傳遞值务傲,換句話說就是調(diào)用閉包 result多次也只能執(zhí)行一次凉当。這就沒辦法讓我們以完整的聲明式的寫法完成需求。

所以要想兩次都觸發(fā)并執(zhí)行RxSwift的訂閱售葡,就不能使用PromiseKit來實現(xiàn)這個網(wǎng)絡(luò)請求看杭。處理很簡單,就是把PromiseKit里面實現(xiàn)網(wǎng)絡(luò)請求的部分提出來改寫即可挟伙。

provider.offLineCacheRequest(.frontpage)
                    .distinctUntilChanged()
                    .filterSuccessfulStatusCodes()
                    .mapJSON()
                    .mapObject(type: HomepageData.self)

我們把這個mapObject后的Observable返回即可楼雹,讓后續(xù)的操作訂閱它。

參考資料

RxSwift vs PromiseKit

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市贮缅,隨后出現(xiàn)的幾起案子榨咐,更是在濱河造成了極大的恐慌,老刑警劉巖谴供,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件块茁,死亡現(xiàn)場離奇詭異,居然都是意外死亡桂肌,警方通過查閱死者的電腦和手機(jī)数焊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來崎场,“玉大人佩耳,你說我怎么就攤上這事√房纾” “怎么了干厚?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長饺蚊。 經(jīng)常有香客問我萍诱,道長,這世上最難降的妖魔是什么污呼? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任裕坊,我火速辦了婚禮,結(jié)果婚禮上燕酷,老公的妹妹穿的比我還像新娘籍凝。我一直安慰自己,他們只是感情好苗缩,可當(dāng)我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布饵蒂。 她就那樣靜靜地躺著,像睡著了一般酱讶。 火紅的嫁衣襯著肌膚如雪退盯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天泻肯,我揣著相機(jī)與錄音渊迁,去河邊找鬼。 笑死灶挟,一個胖子當(dāng)著我的面吹牛琉朽,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播稚铣,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼箱叁,長吁一口氣:“原來是場噩夢啊……” “哼墅垮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起耕漱,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤算色,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后螟够,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剃允,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年齐鲤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片椒楣。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡给郊,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出捧灰,到底是詐尸還是另有隱情淆九,我是刑警寧澤,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布毛俏,位于F島的核電站炭庙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏煌寇。R本人自食惡果不足惜焕蹄,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望阀溶。 院中可真熱鬧腻脏,春花似錦、人聲如沸银锻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽击纬。三九已至鼎姐,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間更振,已是汗流浹背炕桨。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留殃饿,地道東北人谋作。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像乎芳,于是被迫代替她去往敵國和親遵蚜。 傳聞我的和親對象是個殘疾皇子帖池,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,691評論 2 361

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)吭净,斷路器睡汹,智...
    卡卡羅2017閱讀 134,711評論 18 139
  • 秋雨細(xì)如絲,更那堪寂殉、黃葉鋪地囚巴。悵然若失。舊時常笑世間客友扰,盡如走肉行尸彤叉。到而今,往事怯提村怪。徒羨小童騎竹去秽浇,猶自問、怎...
    不才子閱讀 285評論 0 3
  • 微淘惠是一個淘寶天貓購物返利平臺甚负,目前淘寶90%商品都有返利柬焕,有的商品還可以領(lǐng)到內(nèi)部優(yōu)惠券。 微淘惠不會收取您任...
    微淘惠閱讀 760評論 0 0
  • 讀完羅素的這本書之后感觸很深梭域,這本書主要是研究一個人不幸福的原因斑举,怎樣的人是幸福的以及如何去獲得人生中最大的幸福,...
    竹風(fēng)閱讀 715評論 0 1