Безопасно ли разрешать обещание несколько раз?
У меня есть приложение i18n в моем приложении, которое содержит следующий код:
var i18nService = function() {
this.ensureLocaleIsLoaded = function() {
if( !this.existingPromise ) {
this.existingPromise = $q.defer();
var deferred = this.existingPromise;
var userLanguage = $( "body" ).data( "language" );
this.userLanguage = userLanguage;
console.log( "Loading locale '" + userLanguage + "' from server..." );
$http( { method:"get", url:"/i18n/" + userLanguage, cache:true } ).success( function( translations ) {
$rootScope.i18n = translations;
deferred.resolve( $rootScope.i18n );
} );
}
if( $rootScope.i18n ) {
this.existingPromise.resolve( $rootScope.i18n );
}
return this.existingPromise.promise;
};
Идея состоит в том, что пользователь будет называть ensureLocaleIsLoaded
и ждать, пока обещание будет разрешено. Но, учитывая, что цель этой функции состоит в том, чтобы обеспечить загрузку локали, было бы совершенно нормально, если бы пользователь вызывал ее несколько раз.
В настоящее время я просто сохраняю одно обещание и разрешаю его, если пользователь снова вызывает эту функцию после того, как локаль была успешно извлечена с сервера.
Из того, что я могу сказать, это работает по назначению, но мне интересно, подходит ли это подход.
Ответы
Ответ 1
Как я понимаю promises в настоящее время, это должно быть на 100% штрафом. Единственное, что нужно понять, это то, что когда-то разрешено (или отклонено), то есть это для объекта с отсрочкой - это делается.
Если вы должны называть then(...)
на нем обещание снова, вы должны немедленно получить (первый) разрешенный/отклоненный результат.
Дополнительные вызовы resolve()
не будут (не должны?) иметь какой-либо эффект. Не уверен, что произойдет, если вы попытаетесь reject
отложенный объект, который ранее был resolved
(я ничего не подозреваю).
Ответ 2
Если вы хотите разрешить разрешенный объект несколько раз, я рекомендую использовать "DeferredWithUpdate.js"
вы можете найти проект github здесь:
https://github.com/bennadel/DeferredWithUpdate.js
Ответ 3
Я сталкивался с такой же самое некоторое время назад, на самом деле это обещание может быть только решена раз, другой пытается ничего делать не будет (не ошибка, ни предупреждения, ни then
вызова).
Я решил обойти это так:
getUsers(users => showThem(users));
getUsers(callback){
callback(getCachedUsers())
api.getUsers().then(users => callback(users))
}
просто передайте свою функцию в качестве обратного вызова и вызывайте ее столько раз, сколько пожелаете! Надеюсь, что это имеет смысл.
Ответ 4
Что вам нужно сделать, так это положить ng-if на вашу основную ng-розетку и вместо этого показать загрузочный счетчик. Как только ваша локаль загружена, вы показываете выход и даете иерархию компонентов визуализировать. Таким образом, все ваше приложение может предполагать, что локаль загружена и проверки не требуются.
Ответ 5
Если вам нужно изменить возвращаемое значение обещания, просто верните новое значение в then
и вставьте в цепочку следующие then
/catch
var p1 = new Promise((resolve, reject) => { resolve(1) });
var p2 = p1.then(v => {
console.log("First then, value is", v);
return 2;
});
p2.then(v => {
console.log("Second then, value is", v);
});