这个问题很难描述,所以让我发一个例子。
上下文是AngularJS $q
,但任何基于ES6 Promise
的解决方案也是受欢迎的。
假设我们要取消$http
请求。在AngularJS中,这是通过提供承诺A到$http.get()
方法来实现的。解决承诺A将导致取消请求。所以代码看起来像这样:
function httpCall() {
const promiseA = $q.defer();
const promiseB = $http.get(url, { timeout: promiseA.promise });
return promiseB;
}
为了返回promiseA
以便httpCall
的来电者可以取消请求,我找到的唯一方法是将其分配给promiseB
,如下所示:
function httpCall() {
const promiseA = $q.defer();
let promiseB = $http.get(url, { timeout: promiseA });
promiseB.canceller = promiseA;
return promiseB;
}
问题是,promiseB
可以通过长的保证链(例如动作调度,映射,其他后处理)传递,例如:
function doSomeAction() {
return httpCall()
.then((response) => {
processResponse(response);
return response;
});
}
显然,doSomeAction
的返回值与原始承诺promiseB
的承诺不同。
因此,如果我有一个调用doSomeAction()
的函数,则此函数将无法检索promiseB
(它只能获得doSomeAction()
的返回承诺),因此无法取消请求。
有人可能会说我们可以通过链传递数据(promiseA
)。但是我认为promiseA
的存在应该对链本身是透明的,即链中的函数永远不应该知道promiseA
的存在。因此,我不能依赖链为我传递数据。
欢迎任何建议。
答案 0 :(得分:3)
在不同的抽象层次上发生事情时,不了解promiseA
是完全有道理的。 doSomeAction
抽象出http调用并提供任何取消底层http调用的API,打破抽象并揭示doSomeAction
的实现细节。相反,我会考虑使doSomeAction
可取消,即在它返回的对象上提供cancel
方法。这种取消方法可以取消底层的http请求(如果有多个则取消其中几个)或者如果没有发出http请求则跳过取消,数据来自本地存储或对doSomeAction
做任何有意义的事情,而不仅仅是特定的http请求只是该图层中更大图片的一部分。