Используя обещания jQuery, я делаю следующее, чтобы управлять ситуацией, когда у меня есть несколько экземпляров, в которых мне нужно вызывать внешний ресурс, но я не хочу вызывать один и тот же внешний ресурс более одного раза.
{ "somedata": "...", "department": "https://api.../departments/1000", }
Уже глубоко в отдельных вызовах функций для каждого объекта данных я хочу координировать все вызовы одних и тех же ресурсов. Я не хочу получать название отдела для "отдела 1000" несколько раз.
Я сохраняю обещания ИЛИ возвращенный результат в словаре и повторно использую их.
а. Если это обещание, я возвращаю то же обещание, которое будет повторно использовано вызывающей стороной.
б. Если это полученное значение, я разрешаю обещание асинхронно, используя тайм-аут.
Вот код:
var Departments = {};
function getDepartmentName(id){
var dfd = new $.Deferred();
var promise = dfd.promise();
if (id in Departments){
if (typeof Departments[id] == 'object'){
return Departments[id];//reuse the promise
}else{//department name is a string
setTimeout(function(){ dfd.resolve(Departments[id]); }, 0);
}
}
else{
Departments[id] = promise;//Set dictionary value to the promise
var dPromise = FetchDepartment('https://api.../departments/'+id);
$.when(dPromise).then(
function(departmentName){
Departments[id] = departmentName;//Re-set dictionary value to the fetched value
dfd.resolve(departmentName);
},
function(err){
delete Departments[id];
dfd.reject('Call failed');
}
);
}
return promise;
}
Кажется, это работает, но меня беспокоит, настолько ли хорош этот дизайн. У меня есть несколько вопросов.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


I save promises OR a returned result in a dictionary and reuse them. If it is a fetched value, I resolve the promise asynchronous by using a timeout.
Не усложняй. Это ведет себя точно так же, как если бы вы просто сдержали обещание и только вернули его, вместо того, чтобы создавать новые обещания для вызовов после того, как начальное выполнено.
Также избегать отсрочек, когда вы уже имеете дело с обещаниями.
var Departments = {};
function getDepartmentName(id) {
if (id in Departments){
return Departments[id]; //reuse the promise
} else {
var promise = FetchDepartment('https://api.../departments/'+id).then(null, function(err){
delete Departments[id]; // allow retries
throw err;
});
return Departments[id] = promise;
}
}
Is it correct to reuse a promise instance like this, where multiple callers make a call to .then of the same promise object?
Да, это нормально. Их обратные вызовы будут запланированы в том же порядке, что и исходящие вызовы then.
Ага, понятно. Поскольку тогда обратный вызов будет вызван немедленно, в этом случае, если он был вызван после того, как обещание уже было разрешено мне не нужно сохранять значение для повторного использования, я могу просто последовательно сохранять обещание. Высоко оценен и очень хорошо объяснен. Спасибо!