Почему обратные вызовы более "тесно связаны", чем обещания?
Можете ли вы объяснить мне следующую фразу (взято из ответа на вопрос переполнения стека. Каковы различия между отложенным, обещанием и будущим в Javascript?)?
Каковы преимущества использования обещаний jQuery против использования предыдущих обратных вызовов jQuery?
Вместо прямой передачи обратных вызовов функциям, что может привести к тесно связанным интерфейсам, использование обещаний позволяет разделить проблемы для кода, который является синхронным или асинхронным.
5 ответов
Я не думаю, что обещания более или менее связаны, чем обратные вызовы, примерно одинаковые.
Однако обещания имеют и другие преимущества:
Если вы предоставляете обратный вызов, вы должны задокументировать, будет ли он вызываться один раз (как в jQuery.ajax) или несколько раз (как в Array.map). Обещания называются всегда один раз.
Нет способа вызвать функцию обратного вызова и исключение, поэтому вы должны предоставить другой обратный вызов для случая ошибки.
Можно зарегистрировать только один обратный вызов, более одного - для обещаний, и вы можете зарегистрировать их ПОСЛЕ события, и вам все равно позвонят.
В типизированном объявлении (Typescript) Promise облегчает чтение подписи.
В будущем вы можете воспользоваться синтаксисом async / yield.
Поскольку они являются стандартными, вы можете сделать компоненты многократного использования, как этот:
disableScreen<T>(promiseGenerator: () => Promise<T>) : Promise<T> { //create transparent div return promiseGenerator.then(val=> { //remove transparent div return val; }, error=>{ //remove transparent div throw error; }); } disableScreen(()=>$.ajax(....));
Подробнее об этом: http://www.html5rocks.com/en/tutorials/es6/promises/
РЕДАКТИРОВАТЬ:
- Еще одним преимуществом является написание последовательности из N асинхронных вызовов без N уровней отступа.
Кроме того, хотя я все еще не думаю, что это главное, теперь я думаю, что они немного более слабо связаны по этим причинам:
Они являются стандартными (или, по крайней мере, пробуют): код в C# или Java, который использует строки, является более паршивым, чем аналогичный код в C++, потому что существуют различные реализации строк, что делает его более пригодным для повторного использования. Имея стандартное обещание, вызывающая сторона и реализация менее связаны друг с другом, потому что им не нужно согласовывать (пару) пользовательских обратных вызовов с пользовательскими параметрами, порядками, именами и т. Д. Тот факт, что существует много разных Ароматы на обещаниях не помогают мысли.
Они способствуют программированию на основе выражений, упрощают создание, кэширование и т. Д.:
var cache: { [key: string] : Promise<any> }; function getData(key: string): Promise<any> { return cache[key] || (cache[key] = getFromServer(key)); }
Вы можете утверждать, что программирование на основе выражений более свободно связано, чем программирование на основе императивов / обратных вызовов, или, по крайней мере, они преследуют одну и ту же цель: сочетаемость.
Обещание - это объект, представляющий результат асинхронной операции, благодаря чему вы можете передавать его, и это дает вам большую гибкость.
Если вы используете обратный вызов, во время вызова асинхронной операции вы должны указать, как она будет обрабатываться, и, следовательно, связь. С обещаниями вы можете указать, как это будет обрабатываться позже.
Вот пример, представьте, что вы хотите загрузить некоторые данные через ajax, а при этом вы хотите отобразить загрузочную страницу.
С обратными вызовами:
void loadData = function(){
showLoadingScreen();
$.ajax("http://someurl.com", {
complete: function(data){
hideLoadingScreen();
//do something with the data
}
});
};
Обратный вызов, который обрабатывает возвращаемые данные, должен вызывать hideLoadingScreen.
С обещаниями вы можете переписать приведенный выше фрагмент, чтобы он стал более читабельным, и вам не нужно помещать hideLoadingScreen в полный обратный вызов.
С обещаниями
var getData = function(){
showLoadingScreen();
return $.ajax("http://someurl.com").promise().always(hideLoadingScreen);
};
var loadData = function(){
var gettingData = getData();
gettingData.done(doSomethingWithTheData);
}
var doSomethingWithTheData = function(data){
//do something with data
};
ОБНОВЛЕНИЕ: я написал сообщение в блоге, которое содержит дополнительные примеры и дает четкое описание того, что такое обещание и как его использование можно сравнить с использованием обратных вызовов.
Связь более свободна с обещаниями, потому что операция не должна "знать", как она продолжается, она должна знать только, когда она готова.
Когда вы используете обратные вызовы, асинхронная операция на самом деле имеет ссылку на свое продолжение, что не является ее бизнесом.
С помощью обещаний вы можете легко создать выражение для асинхронной операции, прежде чем даже решить, как она будет решаться.
Таким образом, обещания помогают отделить задачи от цепочки событий от фактической работы.
Обещания претворяют в жизнь концепцию отложенного ответа на что-либо. Они делают асинхронные вычисления первоклассным гражданином, так как вы можете их обойти. Они позволяют вам определять структуру, если хотите - монадическую структуру, на которой вы можете создавать комбинаторы более высокого порядка, которые значительно упрощают код.
Например, у вас может быть функция, которая принимает массив обещаний и возвращает обещание массива (обычно это называется sequence
). Это очень сложно сделать или даже невозможно сделать с помощью обратных вызовов. И такие комбинаторы не только облегчают написание кода, но и делают его намного проще для чтения.
Теперь подумайте об обратном, чтобы ответить на ваш вопрос. Обратные вызовы - это специальное решение, в котором обещания обеспечивают более четкую структуру и возможность повторного использования.
Это не так, это просто рационализация, которую люди, которые полностью упускают суть обещаний, используют для оправдания написания гораздо большего количества кода, чем они написали бы с помощью обратных вызовов. Учитывая, что в этом нет никакой пользы, вы, по крайней мере, всегда можете сказать себе, что код менее связан или что-то в этом роде.
Посмотрите, что такое обещания и почему я должен использовать их для реальных конкретных выгод.