Goal
我正在尝试创建一系列承诺“增强器”,它们将围绕现有的承诺(简单的http请求)添加功能(如缓存,排队,重定向处理等) .
Problem
问题是我已经将一个已经增强的承诺包装成了一个非常有用的请求,当我通过返回一个新的 $q
将它包装在一个新的承诺中时,这些问题就会丢失 .
Question
我可以使用什么模式来增强或包装承诺(如下面的两个示例中所示),但不会丢失承诺可能具有的任何其他(非冲突)增强功能?
Example 1
这是一个自动处理503-Retry-After错误的示例:
function _enhancePromiseWithAutoRetry(promise) {
var enhancedPromise = $q(function(resolve, reject) {
var newReject = get503Handler(this, resolve, reject);
promise.then(resolve, newReject);
});
// 503 handling isn't enabled until the user calls this function.
enhancedPromise.withAutoRetry = function(onRetry, timeout) {
var newPromise = angular.copy(this);
newPromise._503handled = true;
newPromise._503onRetry = onRetry;
newPromise._503timeout = timeout;
return newPromise;
};
return enhancedPromise;
}
我的想法是,如果我返回使用上述功能增强的承诺,用户可以:
someRequest.withAutoRetry().then(onSuccess, onError);
或者更清楚(带链接):
someRequest.then(onSuccess, onAnyError)
.withAutoRetry().then(onSuccess, onNon503Error);
在这里,如果服务器忙,第一次调用 then(...)
可能会立即出错,但是 .withAutoRetry()
之后的调用将在重复请求之前轮询服务器,直到响应成功,或者返回非 RetryAfter
错误 .
Example 2
这是另一个添加自定义缓存行为的示例:
function _enhancePromiseWithCache(promise, cacheGet, cachePut) {
// Wrap the old promise with a new one that will get called first.
return $q(function(resolve, reject) {
// Check if the value is cached using the provided function
var cachedResponse = cacheGet !== undefined ? cacheGet() : undefined;
if(cachedResponse !== undefined){
resolve(cachedResponse);
} else {
// Evaluate the wrapped promise, cache the result, then return it.
promise.then(cachePut);
promise.then(resolve, reject);
}
});
}
这个允许库设置数据缓存,可以使用它而不是向服务器发出请求,并且可以在请求完成后添加 . 例如:
lib.getNameOrigin = function(args) {
var restRequest = Restangular.all('people').one(args.id).get('nameOrigin');
// Cache, since all people with the same name will have the same name origin
var enhancedPromise = _enhancePromiseWithCache(restRequest,
function(){ return nameOrigins[args.name]; },
function(val){ nameOrigins[args.name] = val; });
return enhancedPromise;
}
别处
// Will transparently populate the cache
lib.getNameOrigin({id: 123, name:'john'}).then(onSuccess, onError).then(...);
而在其他地方完全
// Will transparently retrieve the result from the cache rather than make request
lib.getNameOrigin({id: 928, name:'john'}).then(onSuccess, onError);
Possible Solution
我've considered copying the original promise, but then overwriting the new one' s then
函数的实现引用了原始的promise then
(使用Proxy Pattern),但这样安全吗?我知道承诺不仅仅是 then
功能 .
2 回答
这是我在 Possible Solution 部分中提出的解决方案,因此可以对其进行详细讨论 .
我've considered copying the original promise, but then overwriting the new one' s
then
函数有一个解决原始承诺的实现,但这样安全吗?New Example
Example 1 (来自上方)
Example 2 (来自上方)
解决方案不是为了增强承诺本身,而是为了创造它们的工厂 .
使用函数式编程和/或面向方面的编程方法来装饰原始函数 . 这不仅会减少错误,而且更简洁,可组合和可重用 .
Example 1:
Example 2: