摘要:假設(shè)家具廠在一周后做完了這個(gè)衣柜,并如約送到了張先生家包郵哦,親,這就叫做衣柜,也就是已解決。這樣,整個(gè)異步流程就圓滿完成,無(wú)論成功或者失敗,張先生都沒(méi)有往里面投入任何額外的時(shí)間成本。
如果想使用 $http 或者其他異步操作, 那 $q 是必須要掌握的概念啦. Let"s get started!
如何理解$q, deferred object ?形象的講解angular中的$q與promise
如何創(chuàng)建 promise -1假設(shè)有一個(gè)家具廠,而它有一個(gè)VIP客戶張先生。
有一天張先生需要一個(gè)豪華衣柜,于是,他打電話給家具廠說(shuō)我需要一個(gè)衣柜,回頭做好了給我送來(lái),這個(gè)操作就叫$q.defer,也就是延期,因?yàn)檫@個(gè)衣柜不是現(xiàn)在要的,所以張先生這是在發(fā)起一個(gè)可延期的請(qǐng)求。
同時(shí),家具廠給他留下了一個(gè)回執(zhí)號(hào),并對(duì)他說(shuō):我們做好了會(huì)給您送過(guò)去,放心吧。這叫做promise,也就是承諾。
這樣,這個(gè)defer算是正式創(chuàng)建了,于是他把這件事記錄在自己的日記上,并且同時(shí)記錄了回執(zhí)號(hào),這叫做deferred,也就是已延期事件。
現(xiàn)在,張先生就不用再去想著這件事了,該做什么做什么,這就是“異步”的含義。
假設(shè)家具廠在一周后做完了這個(gè)衣柜,并如約送到了張先生家(包郵哦,親),這就叫做deferred.resolve(衣柜),也就是“已解決”。而這時(shí)候張先生只要簽收一下這個(gè)(衣柜)參數(shù)就行了,當(dāng)然,這個(gè)“郵包”中也不一定只有衣柜,還可以包含別的東西,比如廠家宣傳資料、產(chǎn)品名錄等。整個(gè)過(guò)程中輕松愉快,誰(shuí)也沒(méi)等誰(shuí),沒(méi)有浪費(fèi)任何時(shí)間。
假設(shè)家具廠在評(píng)估后發(fā)現(xiàn)這個(gè)規(guī)格的衣柜我們做不了,那么它就需要deferred.reject(理由),也就是“拒絕”。拒絕沒(méi)有時(shí)間限制,可以發(fā)生在給出承諾之后的任何時(shí)候,甚至可能發(fā)生在快做完的時(shí)候。而且拒絕時(shí)候的參數(shù)也不僅僅限于理由,還可以包含一個(gè)道歉信,違約金之類的,總之,你想給他什么就給他什么,如果你覺(jué)得不會(huì)惹惱客戶,那么不給也沒(méi)關(guān)系。
假設(shè)家具廠發(fā)現(xiàn),自己正好有一個(gè)符合張先生要求的存貨,它就可以用$q.when(現(xiàn)有衣柜)來(lái)把這個(gè)承諾給張先生,這件事就立即被解決了,皆大歡喜,張先生可不在乎你是從頭做的還是現(xiàn)有的成品,只會(huì)驚嘆于你們的效率之高。
假設(shè)這個(gè)家具廠對(duì)客戶格外的細(xì)心,它還可能通過(guò)deferred.notify(進(jìn)展情況)給張先生發(fā)送進(jìn)展情況的“通知”。
這樣,整個(gè)異步流程就圓滿完成,無(wú)論成功或者失敗,張先生都沒(méi)有往里面投入任何額外的時(shí)間成本。
好,我們?cè)贁U(kuò)展一下這個(gè)故事:
張先生這次需要做一個(gè)桌子,三把椅子,一張席夢(mèng)思,但是他不希望今天收到個(gè)桌子,明天收到個(gè)椅子,后天又得簽收一次席夢(mèng)思,而是希望家具廠做好了之后一次性送過(guò)來(lái),但是他下單的時(shí)候又是分別下單的,那么他就可以重新跟家具廠要一個(gè)包含上述三個(gè)承諾的新承諾,這就是$q.all(桌子承諾,椅子承諾,席夢(mèng)思承諾),
這樣,他就不用再關(guān)注以前的三個(gè)承諾了,直接等待這個(gè)新的承諾完成,到時(shí)候只要一次性簽收了前面的這些承諾就行了。
$q 支持兩種寫(xiě)法, 第一種是類似于ES6標(biāo)準(zhǔn)構(gòu)造函數(shù)寫(xiě)法
$q(function resolver (resolve, reject) {})
注意:
+ ES6 寫(xiě)法并不支持 progress/notify 的回調(diào)函數(shù) + 在構(gòu)造函數(shù)中拋異常也并不會(huì)顯式的reject the promise
// var iWantResolve = false; var iWantResolve = true; function es6promise() { return $q(function (resolve, reject) { $timeout(function () { if (iWantResolve) { resolve("es6promise resolved"); } else { reject("es6promise reject"); } }, 1000) }) }promise 的方法
promise.then(successCb, errCb, notifyCb)
其中successCb 將在 promise resolve 后被調(diào)用, errCb 將在 promise reject 后被調(diào)
notifyCb 將在 deferred.notify 后被調(diào)用, 可以多次調(diào)用
promise.catch == promise.then(null, errCb), 用于處理之前沒(méi)有被處理的 rejected promise
promise.finally 將最后被調(diào)用, 一般用于資源釋放的清理操作
es6promise() .then(function (data) { console.log(data); }) .catch(function (err) { console.log(err); }); // if(iWantResolve == true) output: es6promise resolved // if(iWantResolve = false) output: es6promise reject如何創(chuàng)建 promise -2
第二種是類似于 commonJS 的寫(xiě)法 $q.deferred()
function commonJsPromise() { var deferred = $q.defer(); $timeout(function () { deferred.notify("commonJS notify"); if (iWantResolve) { deferred.resolve("commonJS resolved"); } else { deferred.reject("commonJS reject"); } }, 500); return deferred.promise; } commonJsPromise() .then(function /** success callback**/(data) { console.log(data); }, function /** error callback **/ (err) { console.log(err); }, function /** progress callback **/ (update) { console.log(update); }); // if(iWantResolve == true) output: commonJS notify commonJS resolved // if(iWantResolve = false) output: commonJS notify commonJS reject$q.all
$q.all([promise1, promise1]) 接受一個(gè)包含若干個(gè) promise 的數(shù)組,
等所有的 promise resolve 后, 其本身 resolve 包含上述結(jié)果的數(shù)組 [data1, data2]
如果上述 promise 有一個(gè) reject, 那么$q.all() 會(huì)把這個(gè) rejected promise 作為其 rejected promise (只有一個(gè)哦)
progress/notify 的 callback 并沒(méi)有用
$q.all([es6promise(), commonJsPromise()]) .then(function (dataArr) { console.log("$q.all: ", dataArr); }, function (err) { console.log("$q.all: ", err) }, function /** unnecessary **/ (update) { console.log("$q.all", update); }); // if(iWantResolve == true) output: $q.all: ["es6promise resolved", "commonJS resolved"] // if(iWantResolve = false) output: $q.all: es6promise reject$q.reject, $q.when, $q.resolve
$q.reject() 立即返回一個(gè)rejected 的 promise, 在鏈?zhǔn)秸{(diào)用的時(shí)候很有用
$q.resolve == $q.when(value, successCb, errorCb, progressCb)
value 可能是一個(gè) then-able 的 obj(即可以是 $q.defer() 返回的, 也可以是其他庫(kù)產(chǎn)生的), 也可能是任意數(shù)據(jù), 但是 $q.when 最終都會(huì)返回一個(gè) promise
$q.when 既可以寫(xiě)成上述的構(gòu)造函數(shù)形式, 也可以寫(xiě)成 $q.when(value).then(fn, fn, fn) 的形式
$q.reject("instant reject") .catch(function (err) { console.log(err); }); // output: instant reject $q.when(commonJsPromise(), function /** success callback **/(data) { console.log("$q.when success callback function: " + data); return "$q.when success callback return another value"; }) .then(function (data) { console.log("$q.when then function:" + data); }); // if(iWantResolve == true) output: // $q.when success callback functionL: commonJS resolved // $q.when then function:$q.when success callback return another value // if(iWantResolve = false) output: // $q.when err callback function: commonJS reject // $q.when then function:undefined $q.when("some value", function (data){ console.log(data); }) // output: some valuepromise chains 鏈?zhǔn)秸{(diào)用
任何在 successCb, errCb 中返回的非 $q.reject()對(duì)象, 都將成為一個(gè) resolve 的 promise.
所以可以出現(xiàn)如下語(yǔ)法 promise.then().then().then()
$q.when("1") .then(function (data) { console.log(data); return $q.reject(2); }) .catch(function (err) { console.log(err); return 3; }) .then(function (data) { console.log(data); }) // output: 1 2 3參考資料
AngularJS Documentation for $q
形象的講解angular中的$q與promise
Angular Promise Chaining Explained
$q.when() Is The Missing $q.resolve() Method In AngularJS
How does Angular $q.when work?
$q.when(promise) calls resolve() instead of reject()
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/91589.html
摘要:不過(guò)細(xì)想想,我郵只有前端的選修課啥的,課程也不是那么就業(yè)導(dǎo)向。至少目前,很少有大公司完全把作為前后端通用的技術(shù)棧。不能把簡(jiǎn)單看做是在服務(wù)端的延展。編譯這個(gè)思想在前端領(lǐng)域很重要不改變現(xiàn)有的語(yǔ)言環(huán)境同時(shí)進(jìn)行最佳的工程實(shí)踐。 P.S. 噴神請(qǐng)繞道,大神勿噴,不引戰(zhàn),不攻擊,不鉆牛角尖。 大二時(shí)第一次接觸前端。許多同學(xué)估計(jì)都想過(guò)要做一個(gè)網(wǎng)站,大部分又是從PHP開(kāi)始的(誰(shuí)讓它是世界上最好的語(yǔ)言呢...
摘要:我承認(rèn)從搞笑文章你糟蹋了中得到了一點(diǎn)靈感,不過(guò)我要再次說(shuō)明,我無(wú)意嘲笑框架作者。庫(kù)很好啊,我希望看到大家一致贊同遠(yuǎn)離的是框架。 原文《No more JS frameworks》 中文版翻譯:老碼農(nóng) 翻譯版: 日語(yǔ) JS 框架看上去就像死亡和納稅,必然發(fā)生,無(wú)法避免。如果我能變成一只蒼蠅趴在墻上,我就能確定每次啟動(dòng)一個(gè)新項(xiàng)目的時(shí)候,他們討論的第一個(gè)問(wèn)題肯定是:我們要用哪個(gè) JS ...
摘要:更多資源請(qǐng)文章轉(zhuǎn)自月份前端資源分享視頻前端技術(shù)論壇融合不可錯(cuò)過(guò)的迷你庫(kù)測(cè)試框架實(shí)例教程為你詳細(xì)解讀請(qǐng)求頭的具體含意解析的庫(kù)如果要用前端框架,開(kāi)發(fā)流程是怎樣的與有什么區(qū)別正確使用的方法是什么流程圖插件小如何讓元素只能輸入純文本前端技術(shù)中 更多資源請(qǐng)Star:https://github.com/maidishike... 文章轉(zhuǎn)自:https://github.com/jsfront...
摘要:月份前端資源分享更多資源請(qǐng)文章轉(zhuǎn)自前端生成好看的二維碼十大經(jīng)典排序算法帶動(dòng)圖演示為什么知乎前端圈普遍認(rèn)為游戲和展示的個(gè)人整理和封裝的庫(kù)中文詳細(xì)注釋供新手學(xué)習(xí)使用擴(kuò)展語(yǔ)法記錄掉坑初期工具漢字拼音轉(zhuǎn)換工具實(shí)現(xiàn)漢字轉(zhuǎn)拼音的插件下拉列表支持拼音簡(jiǎn) 2月份前端資源分享 更多資源請(qǐng)Star:https://github.com/maidishike... 文章轉(zhuǎn)自:https://github...
閱讀 3386·2021-11-12 10:36
閱讀 2555·2021-11-02 14:43
閱讀 2206·2019-08-30 14:23
閱讀 3519·2019-08-30 13:08
閱讀 976·2019-08-28 18:09
閱讀 3214·2019-08-26 12:22
閱讀 3226·2019-08-23 18:24
閱讀 2073·2019-08-23 18:17