gpt4 book ai didi

javascript - Angular : Enhancing or wrapping promises with pre/post resolve/reject actions

转载 作者:搜寻专家 更新时间:2023-11-01 04:25:06 25 4
gpt4 key购买 nike

目标

我正在尝试创建一系列 promise “增强器”,这些 promise 将围绕简单的 http 请求等现有 promise 添加功能(例如缓存、排队、重定向处理等)。

问题

我在使用这种增强 promise 的方法时遇到的问题是,如果增强功能向 promise 添加了任何函数或可公开访问的属性(或者如果我正在包装一个已经增强的 promise,例如 restangular 请求),这些是当我通过返回一个新的 $q 将它包装在一个新的 promise 中时丢失了。

问题

我可以使用什么模式来增强或包装 promise(如下面两个示例所示),同时又不会丢失 promises 可能具有的任何其他(非冲突)增强功能?

示例 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;
}

我的想法是,如果我返回一个使用上述功能增强的 promise ,用户可以:

someRequest.withAutoRetry().then(onSuccess, onError);

或者更清楚(使用链接):

someRequest.then(onSuccess, onAnyError)
.withAutoRetry().then(onSuccess, onNon503Error);

这里,如果服务器繁忙,第一次调用 then(...) 可能会立即出错,但 .withAutoRetry() 之后的调用将轮询服务器重复请求直到响应成功,否则返回非RetryAfter错误。

示例 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);

可能的解决方案

我考虑过复制原始 promise ,但随后使用引用原始 promise 的 then 的实现覆盖新的 then 函数(使用 Proxy Pattern ) ,但这安全吗?我知道 promise 不仅仅是 then 函数。

最佳答案

解决方案不是增强 promise 本身,而是增强创建它们的工厂。

使用函数式编程和/或面向方面的编程方法来修饰原始函数。这不仅不容易出错,而且更加简洁、可组合和可重用。

function decorate(makeThenable) {
return function(...args) {
… // before creating the thenable
return makeThenable(...args).then(function(value) {
… // handle fulfillment
return …; // the resulting value
}, function(error) {
… // handle rejection
return …; // (or throw)
});
};
}
var decorated = decorate(myThenablemaker);
decorated(…).then(whenFulfilled, whenRejected);

示例 1:

function withAutoRetry(request, timeout) {
return function() {
var args = arguments;
return request.apply(null, args).catch(function handle(e) {
if (e instanceof Http503Error) // or whatever
return request.apply(null, args).catch(handle);
else
throw e;
});
};
}

withAutoRetry(someRequest)().then(onSuccess, onError);

withAutoRetry(function() {
return someRequest().then(onSuccess, onAnyError);
})().then(onSuccess, onNon503Error);

示例 2:

function withCache(request, hash) {
var cache = {};
if (!hash) hash = String;
return function() {
var key = hash.apply(this, arguments);
if (key in cache)
return cache[key];
else
return cache[key] = request.apply(this, arguments);
};
}

lib.getNameOrigin = withCache(function(args) {
return Restangular.all('people').one(args.id).get('nameOrigin');
}, function(args) {
return args.name;
});

关于javascript - Angular : Enhancing or wrapping promises with pre/post resolve/reject actions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25429386/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com