Почему обратные вызовы более "плотно связаны", чем promises?

Можете ли вы объяснить мне следующую фразу (взятую из ответ на вопрос о переполнении стека Какие различия между отложенными, обещаниями и будущими в Javascript?)?

Каковы преимущества использования jQuery promises против использования предыдущих обратных вызовов jQuery?

Вместо прямого прохождения обратных вызовов к функциям, что-то, что может привести к плотно сопряженным интерфейсам, использование promises позволяет отдельные проблемы для синхронного или асинхронного кода.

Ответ 1

Я не думаю, что promises более или менее связаны, чем обратные вызовы, примерно то же самое.

Promises имеют другие преимущества:

  • Если вы вызываете обратный вызов, вы должны документировать, будет ли он вызываться один раз (например, в jQuery.ajax) или более одного раза (например, в Array.map). promises вызываются всегда один раз.

  • Нет способа вызвать обратный вызов и исключение на нем, поэтому вам нужно предоставить другой обратный вызов для случая ошибки.

  • Только один обратный вызов может быть зарегистрирован, более одного для promises, и вы можете зарегистрировать их ПОСЛЕ события, и вы все равно получите вызов.

  • В типизированном объявлении (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/

EDIT:

  • Еще одно преимущество заключается в написании последовательности N асинхронных вызовов без N уровней отступов.

Кроме того, хотя я до сих пор не думаю, что это главное, теперь я думаю, что они немного более слабо связаны по следующим причинам:

  • Они стандартные (или, по крайней мере, попытка): код на С# или Java, который использует строки, более паршиво связан с аналогичным кодом на С++, потому что различные реализации строк там, что делает его более многоразовым. Имея стандартное обещание, вызывающий и реализация менее связаны друг с другом, потому что им не нужно соглашаться на (пару) пользовательских обратных вызовов с пользовательскими параметрами заказов, имен и т.д. Тот факт, что существует много разных ароматы на promises не помогают мысли.

  • Они продвигают более основанное на выражении программирование, упрощают сбор, кеширование и т.д.:

      var cache: { [key: string] : Promise<any> };
    
      function getData(key: string): Promise<any> {
          return cache[key] || (cache[key] = getFromServer(key)); 
      }
    

вы можете утверждать, что программирование на основе выражений более слабо связано, чем программирование на основе обязательного/обратного вызова, или, по крайней мере, они преследуют одну и ту же цель: способность к компромиссу.

Ответ 2

Обещание - это объект, представляющий результат асинхронной операции, и из-за этого вы можете передать его, и это дает вам больше гибкости.

Если вы используете обратный вызов, во время вызова асинхронной операции вы должны указать, как она будет обрабатываться, следовательно, связь. С помощью promises вы можете указать, как будет обрабатываться позже.

Вот пример, представьте, что вы хотите загрузить некоторые данные через ajax и при этом хотите отобразить страницу загрузки.

С обратными вызовами:

void loadData = function(){
  showLoadingScreen();
  $.ajax("http://someurl.com", {
    complete: function(data){
      hideLoadingScreen();
      //do something with the data
    }
  });
};

Обратный вызов, который обрабатывает возвращаемые данные, должен вызвать hideLoadingScreen.

С promises вы можете переписать фрагмент выше, чтобы он стал более читаемым, и вам не нужно помещать hideLoadingScreen в полный обратный вызов.

С promises

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

ОБНОВЛЕНИЕ: Я написал сообщение в блоге, в котором приводятся дополнительные примеры и дается четкое описание того, что является обещанием и как его использование можно сравнить с использованием обратных вызовов.

Ответ 3

Связь слабее с promises, потому что операция не должна "знать", как она продолжается, она должна знать только, когда она готова.

Когда вы используете обратные вызовы, асинхронная операция фактически имеет ссылку на ее продолжение, что не является ее бизнесом.

С помощью promises вы можете легко создать выражение над асинхронной операцией, прежде чем вы даже решите, как оно будет разрешаться.

Итак, promises помогает разделить проблемы цепочек событий и выполнять фактическую работу.

Ответ 4

Promises подтверждают концепцию отложенного ответа на что-то. Они делают асинхронное вычисление первоклассным гражданином, поскольку вы можете передать его. Они позволяют вам определять структуру, если хотите, монадическую структуру, на которой вы можете создавать комбинаторы более высокого порядка, которые значительно упрощают код.

Например, у вас может быть функция, которая принимает массив promises и возвращает обещание массива (обычно это называется sequence). Это очень сложно сделать или даже невозможно с обратными вызовами. И такие комбинаторы не просто делают код более удобным для записи, тем легче читать.

Теперь рассмотрим другой вопрос, чтобы ответить на ваш вопрос. Обратные вызовы - это ad-hoc-решение, где promises обеспечивает более четкую структуру и повторное использование.

Ответ 5

Это не так, это просто рационализация того, что люди, которые полностью упускают точку promises, используют для оправдания написания гораздо большего кода, чем они будут писать с использованием обратных вызовов. Учитывая, что в этом нет никакой пользы, вы можете по крайней мере всегда сказать себе, что код менее связан или что-то в этом роде.

Смотрите что такое promises и почему я должен использовать их для получения конкретных конкретных преимуществ.