AngularJS:通过 promises 获取 "asynchronous" 调用的基础进展
AngularJS: obtain underlying progression of an "asynchronous" call via promises
所以,我们目前有类似这样的东西用于向后端的异步请求。
首先:GenericApi 用于所有应用程序
get: function (url) {
return api_bridge ({
execute: function (auth_headers) {
return $q.resolve($http.get(vm.urlBase + url, {headers: auth_headers}));
}
}).then(handlerSuccessResponse, handlerErrorResponse);
}
然后是处理程序方法
//error
function handlerErrorResponse(response) {
return $q.reject(response);
}
//success
function handlerSuccessResponse(response) {
if (response.isAsync) {
return asyncStatus(response.taskId);
} else {
return $q.resolve(response);
}
}
这里成功拿到钥匙,因为如果是异步方法,就递归调用这个方法:
function asyncStatus(id){
return getAsyncStatus(id).then(function(response){
if (response.progress < 100){
return asyncStatus(id);
} else {
return getAsyncResult(id);
}
});
}
调用其中一个:
getAsyncStatus: function(id){
return get('/async/status/' + id);
},
getAsyncResult: function(id){
return get('/async/result/' + id);
},
(再次调用此列表的第一个方法)。
这样我们就可以做一个 getter 我们永远不会关心幕后发生的事情:
get("/myurl")
.then(successMethod)
.catch(errorMethod);
(无论是否异步,这都将以相同的方式工作)
但现在我们想升级这个系统,以便能够在每次调用 asyncStatus 时进行回调。理想情况下是这样的:
get("/myurl")
.then(successMethod)
.catch(errorMethod)
.progression(progressMethod);
最明显的方法是将一个方法作为参数传递给所有链,然后在 getAsyncStatus 的每次迭代中调用它,但这种方法违背了所有方法的目的这在引擎盖下有一个黑盒子,没有人需要担心,加上改变这意味着改变所有当前现有的方法。
为了使其尽可能接近示例,我想我必须用 $q.defer().notify() 做一些事情,但我似乎无法正确理解这个概念。这样做不起作用:
get("/myurl")
.then(successMethod, null, progressMethod)
.catch(errorMethod);
我不知道如何让它工作。
好吧,显然 api_bridge 方法破坏了 promise 绑定。发现解决方案是这样做的:
通用 获取:
get: function (url) {
var dfr = $q.defer();
dfr.resolve( api_bridge ({
execute: function (auth_headers) {
return $q.resolve($http.get(vm.urlBase + url, {headers: auth_headers}));
}
}));
return dfr.promise.then(handlerSuccessResponse, handlerErrorResponse);
}
处理程序方法(无变化):
//error
function handlerErrorResponse(response) {
return $q.reject(response);
}
//success
function handlerSuccessResponse(response) {
if (response.isAsync) {
return asyncStatus(response.taskId);
} else {
return $q.resolve(response);
}
}
递归异步方法:
function asyncStatus(id){
var deferred = $q.defer();
var deferred.promise.then(null, null, angular.noop);
var deferred.notify("This is a notification");
deferred.resolve(getAsyncStatus(id).then(function(response){
if (response.progress < 100){
return asyncStatus(id);
} else {
return getAsyncResult(id);
}
}));
return deferred.promise;
}
调用其中任何一个(不变);
getAsyncStatus: function(id){
return get('/async/status/' + id);
},
getAsyncResult: function(id){
return get('/async/result/' + id);
},
现在我们可以做:
get("/myurl")
.then(successMethod, null, progressMethod)
.catch(errorMethod);
Callback progressMethod 将在每次 asyncStatus 抛出通知时调用。
所以,我们目前有类似这样的东西用于向后端的异步请求。
首先:GenericApi 用于所有应用程序
get: function (url) {
return api_bridge ({
execute: function (auth_headers) {
return $q.resolve($http.get(vm.urlBase + url, {headers: auth_headers}));
}
}).then(handlerSuccessResponse, handlerErrorResponse);
}
然后是处理程序方法
//error
function handlerErrorResponse(response) {
return $q.reject(response);
}
//success
function handlerSuccessResponse(response) {
if (response.isAsync) {
return asyncStatus(response.taskId);
} else {
return $q.resolve(response);
}
}
这里成功拿到钥匙,因为如果是异步方法,就递归调用这个方法:
function asyncStatus(id){
return getAsyncStatus(id).then(function(response){
if (response.progress < 100){
return asyncStatus(id);
} else {
return getAsyncResult(id);
}
});
}
调用其中一个:
getAsyncStatus: function(id){
return get('/async/status/' + id);
},
getAsyncResult: function(id){
return get('/async/result/' + id);
},
(再次调用此列表的第一个方法)。
这样我们就可以做一个 getter 我们永远不会关心幕后发生的事情:
get("/myurl")
.then(successMethod)
.catch(errorMethod);
(无论是否异步,这都将以相同的方式工作)
但现在我们想升级这个系统,以便能够在每次调用 asyncStatus 时进行回调。理想情况下是这样的:
get("/myurl")
.then(successMethod)
.catch(errorMethod)
.progression(progressMethod);
最明显的方法是将一个方法作为参数传递给所有链,然后在 getAsyncStatus 的每次迭代中调用它,但这种方法违背了所有方法的目的这在引擎盖下有一个黑盒子,没有人需要担心,加上改变这意味着改变所有当前现有的方法。
为了使其尽可能接近示例,我想我必须用 $q.defer().notify() 做一些事情,但我似乎无法正确理解这个概念。这样做不起作用:
get("/myurl")
.then(successMethod, null, progressMethod)
.catch(errorMethod);
我不知道如何让它工作。
好吧,显然 api_bridge 方法破坏了 promise 绑定。发现解决方案是这样做的:
通用 获取:
get: function (url) {
var dfr = $q.defer();
dfr.resolve( api_bridge ({
execute: function (auth_headers) {
return $q.resolve($http.get(vm.urlBase + url, {headers: auth_headers}));
}
}));
return dfr.promise.then(handlerSuccessResponse, handlerErrorResponse);
}
处理程序方法(无变化):
//error
function handlerErrorResponse(response) {
return $q.reject(response);
}
//success
function handlerSuccessResponse(response) {
if (response.isAsync) {
return asyncStatus(response.taskId);
} else {
return $q.resolve(response);
}
}
递归异步方法:
function asyncStatus(id){
var deferred = $q.defer();
var deferred.promise.then(null, null, angular.noop);
var deferred.notify("This is a notification");
deferred.resolve(getAsyncStatus(id).then(function(response){
if (response.progress < 100){
return asyncStatus(id);
} else {
return getAsyncResult(id);
}
}));
return deferred.promise;
}
调用其中任何一个(不变);
getAsyncStatus: function(id){
return get('/async/status/' + id);
},
getAsyncResult: function(id){
return get('/async/result/' + id);
},
现在我们可以做:
get("/myurl")
.then(successMethod, null, progressMethod)
.catch(errorMethod);
Callback progressMethod 将在每次 asyncStatus 抛出通知时调用。