promise是JavaScript中處理異步事務的一種方式,這樣的事務會在後續的某個時間點上完成。通常會在使用Ajax請求的時候使用到promise,瀏覽器在後臺發起HTTP請求,並且在請求完成後使用promise通知相應的應用程序。以下程序示例,演示了一個極簡單的AngularJS應用,並在其中調用Ajax請求。
<!DOCTYPE html>
<html ng-app="demo">
<head>
<meta charset="utf-8">
<title>Example</title>
<link rel="stylesheet" href="bootstrap.css">
</head>
<body ng-controller="demoCtrl">
<div class="panel"></div>
<h1>To Do</h1>
<table class="table">
<tr>
<td>Action</td>
<td>Done</td>
</tr>
<tr ng-repeat="item in todos">
<td>{{item.action}}</td>
<td>{{item.done</td>
</tr>
</table>
<script src="angular.js"></script>
<script>
var app = angular.module('demo', []);
app.controller('demoCtrl', ['$scope', '$http', function ($scope, $http) {
var promise = $http.get('todo.json');
promise.success(function(data){
$scope.todos = data;
})
}])
</script>
</body>
</html>
爲了演示promise是如何工作的,我還需要設置AngularJS中的模塊、控制器、視圖等組成部分。其中關鍵的代碼如下:
var promise = $http.get('todo.json');
promise.success(function(data){
$scope.todos = data;
});
$http服務用來發起Ajax請求,它的get方法接受你想從服務端獲得文件的URL作爲參數。
Ajax請求的處理是異步的,在這個請求的過程,瀏覽器會繼續執行其它的代碼。$http.get方法會返回一個promise對象,通過這個對象可以獲取Ajax請求的相關信息。如在這個例子中,我使用了success方法來註冊一個回調函數,這個回調函數將在請求成功完成之後被調用。回調函數接收從服務端返回的數據,我將這些數據賦值給了$scope對象的todos屬性,這樣,也爲ng-repeat指令提供了在表格中需要顯示的內容。success方法是在promise對象中定義的三個方法中的其中一個,如下表所示:
promise對象中定義的方法
名稱 | 描述 |
error(callback) | 指定一個回調函數,這個回調函數將在promise處理的任務未能成功完成時被調用 |
success(callback) | 指定一個回調函數,這個回調函數將在promise處理的任務成功完成時被調用 |
then(success, err) | 爲promise分別指定一個執行成功或失敗的回調函數 |
三個方法的參數都是函數,而這些函數將根據promise執行的結果決定是否被執行。可以將從服務端獲得的數據傳給success方法的回調函數中,而error方法的回調函數中可以得到錯誤的詳細信息。
三個promise方法還可以返回其他的promise對象,這樣就可以將異步的任務通過鏈式的寫法寫在一起,如下:
<!DOCTYPE html>
<html ng-app="demo">
<head>
<meta charset="utf-8">
<title>Example</title>
<link rel="stylesheet" href="boostrap3/css/bootstrap.min.css" />
</head>
<body ng-controller="demoCtrl">
<div class="panel">
<h1>To Do</h1>
<table class="table table-striped">
<tr>
<td>Action</td>
<td>Done</td>
</tr>
<tr ng-repeat="item in todos">
<td>{{item.action}}</td>
<td>{{item.done}}</td>
</tr>
</table>
</div>
<script src="js/angular/angular.min.js"></script>
<script>
var myApp = angular.module('demo', []);
myApp.controller('demoCtrl', ['$scope', '$http', function($scope, $http){
$http.get('data/todo.json').then(function(response){
$scope.todos = response.data;
}, function(){
$scope.todos = [{action: 'Error'}];
}).then(function(){
$scope.todos.push({action: 'Request Complete'})
})
}])
</script>
</body>
</html>
這裏兩次使用了then方法,第一次用以處理$http.get請求的響應,並且還註冊了一個隨後會被調用的函數。這樣的代碼可能會難以閱讀,所以下面可以分步來了解它們。首先,調用get方法來創建一個Ajax請求:
<strong>$http.get('data/todo.json')</strong>.then(function(response){
$scope.todos = response.data;
}, function(){
$scope.todos = [{action: 'Error'}];
}).then(function(){
$scope.todos.push({action: 'Request Complete'})
});
接着,使用then方法,並且提供了在Ajax請求完成時會被調用的回調函數。當請求成功時會調用第一個函數,而失敗時會執行第二個函數。
$http.get('data/todo.json').<strong>then(function(response){
$scope.todos = response.data;
}, function(){
$scope.todos = [{action: 'Error'}];
})</strong>.then(function(){
$scope.todos.push({action: 'Request Complete'})
});
promise確保了這兩個函數會被執行,但是隻有在Ajax請求成功完成或失敗的時候纔會執行。隨後再次使用了then方法添加了另一個函數:
$http.get('data/todo.json').then(function(response){
$scope.todos = response.data;
}, function(){
$scope.todos = [{action: 'Error'}];
})<strong>.then(function(){
$scope.todos.push({action: 'Request Complete'})
})</strong>;
這次只傳了一個函數給then方法,意味着我們不處理出錯的情況。最後個函數不管前面的函數是否被調用都會想數據模型裏面添加一個數據項。Ajax請求調用成功的效果如下圖所示: