這是我在翻閱資料的時(shí)候,在國(guó)外的thinkster上找到的一篇關(guān)于關(guān)于angular中promise的一篇資料教程,寫(xiě)的非常好,收益良多,我現(xiàn)在翻譯一下,供大家學(xué)習(xí)交流,如果大家想深入學(xué)習(xí),歡迎到thinkster注冊(cè),并且付費(fèi)。
下面是正文:
angular的promise是由$q提供和構(gòu)件的,$q提供了一個(gè)通過(guò)注冊(cè)一個(gè)promise項(xiàng)目來(lái)異步執(zhí)行的方法。Promise作為ES6的一部分規(guī)范形成了原生javascript。angular的$q服務(wù)提供了一個(gè)新的接口,方便與以后移植到ES6。
code
<html>
<head>
<tittle>Promise fun</tittle>
</head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0-beta.5/angular.min.js"></script>
<script src="app.js"></script>
<body ng-app="app">
</body>
</html>
function getData($timeout, $q) {
return function() {
var defer = $q.defer()
// simulated async function
$timeout(function() {
}, 2000)
return defer.promise
}
}
angular.module('app', [])
.factory('getData', getData)//把getData方法進(jìn)入factory進(jìn)行實(shí)例化,方便進(jìn)去run方法進(jìn)行配置
.run(function(getData) {//run方法用于快速配置,注入完成后啟動(dòng)(只能是實(shí)例化的服務(wù)或者參數(shù)可以配置)
var promise = getData()
})
為了簡(jiǎn)單起見(jiàn),我們使用angular的$timeout服務(wù)模擬異步函數(shù),尤其是講解AJAX使用angular的$HTTP服務(wù),是最常用使用promise的地方
異步對(duì)象
延遲對(duì)象是一個(gè)簡(jiǎn)單的對(duì)象當(dāng)為了解決這個(gè)promise對(duì)象暴露出一個(gè)promise對(duì)象,它是使用$q.defer()方法來(lái)構(gòu)建,并且暴露出三個(gè)主要的方法,resolve() reject()和notify();這個(gè)相關(guān)聯(lián)的promise對(duì)象能夠通過(guò)promise對(duì)象屬性來(lái)訪問(wèn).
function getData(){
return function(){
var defer=$q.defer();
$timeout(function(){
defer.resolve("data received");
},2000);
return defer.promise;
}
}
這里創(chuàng)建了一個(gè)promise對(duì)象,然后返回promise對(duì)象的屬性,執(zhí)行異步函數(shù)當(dāng)函數(shù)完成后,我們解析這個(gè)延遲對(duì)象,這個(gè)resoleve()函數(shù)的參數(shù)會(huì)被傳遞到回調(diào)函數(shù)中。
Promise對(duì)象
現(xiàn)在我們獲得了一個(gè)promise對(duì)象(defer.promise),讓我們注冊(cè)一個(gè)回調(diào)函數(shù),當(dāng)異步函數(shù)完成后執(zhí)行。使用then()方法,附加一個(gè)回調(diào)函數(shù),用來(lái)返回promise對(duì)象用來(lái)打印返回的string對(duì)象。
.run(function(getData){
var promise=getData()
.then(function(){
console.log(string);
})
})
拒絕一個(gè)promise對(duì)象
我們已經(jīng)見(jiàn)過(guò)如何成功解析一個(gè)promise對(duì)象,但是當(dāng)異步函數(shù)失敗的時(shí)候會(huì)發(fā)生什么,相比于使用Resolve()方法,我們稱reject()方法如果當(dāng)失敗的時(shí)候使用。
使用Math.random()來(lái)模擬失敗然后返回這個(gè)promise對(duì)象,一半的機(jī)會(huì)。
function getData($timeout,$q){
var defer=$q.defer();
$timeout(function(){
if(Math.round(Math.rondom())){
defer.solve('data received!')
}else{
defer.reject('oh no an error! try again');
}
},2000)
return defer.promise;
}
then()方法的第二個(gè)參數(shù)是一個(gè)可選的發(fā)生錯(cuò)誤時(shí)候的回調(diào)函數(shù),當(dāng)這個(gè)promise對(duì)象失敗的時(shí)候調(diào)用。
給then()傳入第二個(gè)作為執(zhí)行發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。
.run(function(getData){
var promise=getData()
.then(function(string){
console.log(string)
},function(error){
console.log(error);
})
})
使用$q構(gòu)造函數(shù)
使用$q服務(wù)本身能夠快速變換一個(gè)基于異步函數(shù)的回調(diào)函數(shù),形成一種快速解決方案。
重寫(xiě)這個(gè)模擬的異步函數(shù)用來(lái)返回一個(gè)promise對(duì)象使用$q函數(shù)。
function($timeout,$q){
return function(){
return $q(function(resolve,reject){
$timeout(function(){
if(Math.ronund(Math.random())){
resolve('data received!')
}else{
reject('oh no an error! try again')
}
},2000)
})
}
}
這個(gè)方法完成了同樣的事情,手動(dòng)的創(chuàng)建了一個(gè)延遲對(duì)象,
finally()方法
promise對(duì)象只能成功執(zhí)行函數(shù)或者失敗回調(diào)函數(shù)能夠被執(zhí)行,但不是全部。但是當(dāng)你需要確保這個(gè)方法執(zhí)行忽略promise的結(jié)果。你可以通過(guò)使用finally()來(lái)注冊(cè)這個(gè)方法,當(dāng)對(duì)于一個(gè)已知狀態(tài)的時(shí)候,很有用。
使用這個(gè)finally()方法來(lái)打印相應(yīng)時(shí)間間隔,當(dāng)異步函數(shù)完成時(shí)。
.run(function(getData) {
var promise = getData()
.then(function(string) {
console.log(string)
}, function(error) {
console.error(error)
})
.finally(function() {
console.log('Finished at:', new Date())
})
})
現(xiàn)在你可以看到現(xiàn)在時(shí)間被打印出來(lái),忽略了promise執(zhí)行的狀態(tài)。
promise鏈
最有魅力的promise特性就是能夠使用使用鏈鏈接起來(lái)。它允許數(shù)據(jù)通過(guò)這個(gè)鏈流動(dòng),并且每一步進(jìn)行操作和突變。
簡(jiǎn)單的示例:
現(xiàn)在修改我們的異步函數(shù),用來(lái)傳遞一個(gè)0-9之間的隨機(jī)數(shù),到resolve()函數(shù)
function getData($timeout, $q) {
return function() {
// simulated async function
return $q(function(resolve, reject) {
$timeout(function() {
resolve(Math.floor(Math.random() * 10))
}, 2000)
})
}
}
當(dāng)頁(yè)面刷新,可以看到一個(gè)隨機(jī)的interger數(shù)字在0-9之間跳動(dòng)。
為了開(kāi)始鏈?zhǔn)秸{(diào)用,我們必須修改這個(gè)回調(diào)函數(shù)返回一個(gè)value。
修改這個(gè)promise調(diào)用的回調(diào)函數(shù)用來(lái)返回一個(gè)隨機(jī)數(shù)乘以2。
.run(function(getData) {
var promise = getData()
.then(function(num) {
console.log(num)
return num * 2
})
})
現(xiàn)在我們能夠鏈?zhǔn)秸{(diào)用另外一個(gè)回調(diào)函數(shù)對(duì)象使用then()方法,能夠在第一個(gè)回調(diào)函數(shù)被執(zhí)行后返回,這個(gè)值傳入第二個(gè)回調(diào)函數(shù)被乘以2。
.run(function(getData) {
var promise = getData()
.then(function(num) {
console.log(num)
return num * 2
})
.then(function(num) {
console.log(num) // = random number * 2
})
})
這個(gè)例子雖然簡(jiǎn)單,但是說(shuō)明了一個(gè)強(qiáng)大的概念,此外,不僅僅是從promise回調(diào)返回一個(gè)簡(jiǎn)單的值,能夠返回新的promise對(duì)象。這個(gè)作用域鏈會(huì)暫停,知道返回這個(gè)回調(diào)成功。這樣允許把多個(gè)異步回調(diào)串在一起。
下面是原文的連接,如果大家喜歡,可以到原網(wǎng)站學(xué)習(xí)。https://thinkster.io/a-better-way-to-learn-angularjs/promises
本文可以隨意轉(zhuǎn)載,但需注明出處。http://www.itdecent.cn/p/df257dfbc8fe
這是我的github 文章分享的地方,歡迎交流。https://github.com/vista5004/article