我使用延迟承诺中止$http
请求(如this帖子中所述)。
但是,我不确定如何传播在根级别添加的abort()
函数。每次我在promise上调用.then()
时,都会返回一个新的promise(没有abort()
函数)。
请参阅下面的示例。我有一个控制器调用服务,然后调用另一个服务(发出$http
请求的地方)。该示例不起作用,因为promise
中的MyController
与restService
中返回的abort()
不同,因此没有名为abort()
的函数。< / p>
MyController
功能,使其在then()
中可用?then()
(如底部示例中所示)? app.controller("MyController", function($scope, dataService) {
var promise;
$scope.loadAndAbortData = function () {
promise = dataService.getData().then(updateUI);
};
$scope.abort = function () {
if (promise) {
promise.abort();
}
};
}
来电会怎么样?它们是否仍被同步调用&#34;?app.service("dataService", function(restService) {
var service = {
getData: function () {
return restService.get().then(function (response) {
var modifiedData = modifyData(response.data);
return modifiedData;
}, function (response) {
handleError(response.data);
$q.reject(response.data);
});
};
};
return service;
}
app.service("restService", function($http, $q) {
var service = {
get: function () {
var deferredAbort = $q.defer();
var request = $http.get(url, { timeout: deferredAbort.promise } );
promise.abort = function () {
deferredAbort.resolve();
}
return promise;
};
};
return service;
}
app.controller("MyController", function($scope, dataService) {
var promise;
$scope.loadAndAbortData = function () {
promise = dataService.getData();
promise.then(updateUI);
};
$scope.abort = function () {
if (promise) {
promise.abort();
}
};
}
app.service("dataService", function(restService) {
var service = {
getData: function () {
var promise = restService.get();
promise.then(function (response) {
var modifiedData = modifyData(response.data);
return modifiedData;
}, function (response) {
handleError(response.data);
$q.reject(response.data);
});
return promise;
};
};
return service;
}
{{1}}
答案 0 :(得分:1)
整个事情似乎取决于在RestService中,在timeout: Promise
配置映射中提供可解析的$http()
选项,并以某种方式返回带有.abort()
方法的promise以及其标准方法;然后确保.abort()
方法&#34;继承&#34;通过DataService,进入Controller。为实现这一目标,需要一些小技巧。
我猜你可以这样做:
//RestService:
app.service("restService", function($http, $q) {
return {
get: function () {
var dfrd = $q.defer(),
promise = $http.get(url, {
timeout: dfrd.promise
});
//attach the deferred's resolve method as promise's abort method
promise.abort = dfrd.resolve.bind(dfrd);//(or with an explicit function wrapper, as in the question)
return promise;
},
};
}
同样,在DataService中,返回的promise需要一个abort
方法,该方法再次引用回RestService中的dfrd.resolve
方法。
//DataService
app.service("dataService", function(restService) {
return {
getData: function () {
//Here, the natural syntax would be `return restService.get().then(...)`,
//however a reference to intermediate `restService.get()` is required such that its special `.abort()` method can be attached as the `.abort()` method of the eventually returned promise.
var promise = restService.get();
var promise_ = promise.then(function(response) {
var modifiedData = modifyData(response.data);
return modifiedData;
}, function (response) {
handleError(response.data);
$q.reject(response.data);
});
promise_.abort = promise.abort;//attach promise's abort method as promise_'s abort method.
return promise_;
}
};
});
因此,dataService.getData()
应该使用abort
方法向Controller传递承诺。
//Controller
app.controller("MyController", function($scope, dataService) {
var promise;
//Here, play the same trick as in the DataService -
//ie. assign the intermediate promise rather than the output of the full chain.
$scope.loadAndAbortData = function () {
promise = dataService.getData();
promise.then(updateUI);
};
$scope.abort = function () {
if (promise && promise.abort) {
promise.abort();
}
};
}
答案 1 :(得分:0)
我最终找到了一个“覆盖”承诺的then()
函数的解决方案,以便abort()
函数将遍历所有图层,而与then()/catch()/finally()
的次数无关。在承诺上被召唤。
如果有人找到更好的解决方案或者看到这个问题存在缺陷,我真的很感激一些意见。
app.service("restService", function($http, $q) {
function createAbortablePromise(promise, deferredAbort) {
promise.abort = function () {
deferredAbort.resolve();
};
// A problem with adding the abort function to the promise is that as soon as someone
// calls then() on this promise (somewhere else in our application), another new promise
// is returned. This new promise, will not have the abort() function. We can solve this
// by "overriding" then() recursively.
var originalThen = promise.then;
promise.then = function (callback, errback, progressback) {
// Invoke the original then(). It will return a new promise
var newPromise = originalThen(callback, errback, progressback);
// This new promise needs an abort function as well.
newPromise = createAbortablePromise(newPromise, deferredAbort);
return newPromise;
};
return promise;
}
var service = {
get: function () {
var deferredAbort = $q.defer();
var request = $http.get(url, { timeout: deferredAbort.promise } );
promise.abort = function () {
deferredAbort.resolve();
}
promise = createAbortablePromise(promise, deferredAbort);
return promise;
};
};
return service;
}