Что означает функция then () в JavaScript? - PullRequest
223 голосов
/ 07 октября 2010

Я вижу код, который выглядит следующим образом:

myObj.doSome("task").then(function(env) {
    // logic
});

Откуда взялся then()?

Ответы [ 9 ]

262 голосов
/ 16 июля 2015

Традиционный способ обработки асинхронных вызовов в JavaScript - обратные вызовы. Скажем, нам нужно было сделать три звонка на сервер, один за другим, чтобы настроить наш приложение. С обратными вызовами код может выглядеть примерно так: функция xhrGET для вызова сервера):

// Fetch some server configuration
    xhrGET('/api/server-config', function(config) {
        // Fetch the user information, if he's logged in
        xhrGET('/api/' + config.USER_END_POINT, function(user) {
            // Fetch the items for the user
            xhrGET('/api/' + user.id + '/items', function(items) {
                // Actually display the items here
            });
        });
    });

В этом примере мы сначала выбираем конфигурацию сервера. Затем на основе этого мы получаем информация о текущем пользователе, а затем, наконец, получить список элементов для текущего пользователь. Каждый вызов xhrGET принимает функцию обратного вызова, которая выполняется, когда сервер отвечает.

Теперь, конечно, чем больше у нас уровней вложенности, тем сложнее код читать, отлаживать, поддерживать, обновлять и в основном работать с. Это вообще известно как ад обратного вызова. Кроме того, если нам нужно обработать ошибки, нам, возможно, нужно передать другую функцию каждому Вызов xhrGET, чтобы сообщить, что нужно делать в случае ошибки. Если бы мы хотели иметь только один общий обработчик ошибок, это невозможно.

API Promise был разработан для решения этой проблемы со проблема обработки ошибок.

API Promise предлагает следующее:

  1. Каждая асинхронная задача возвращает объект promise.
  2. Каждый объект promise будет иметь функцию then, которая может принимать два аргумента, success обработчик и обработчик error.
  3. Успешный или обработчик ошибок в функции then будет вызываться только один раз , после асинхронная задача завершается.
  4. Функция then также возвращает promise, чтобы разрешить цепочку из нескольких вызовов.
  5. Каждый обработчик (успех или ошибка) может вернуть value, который будет передан следующему функционировать как argument, в цепочке promise с.
  6. Если обработчик возвращает promise (делает другой асинхронный запрос), то следующий Обработчик (успех или ошибка) будет вызван только после того, как этот запрос будет завершен.

Так что предыдущий пример кода может перевести что-то вроде следующего, используя обещания и сервис $http (в AngularJs):

$http.get('/api/server-config').then(
    function(configResponse) {
        return $http.get('/api/' + configResponse.data.USER_END_POINT);
    }
).then(
    function(userResponse) {
        return $http.get('/api/' + userResponse.data.id + '/items');
    }
).then(
    function(itemResponse) {
        // Display items here
    }, 
    function(error) {
        // Common error handling
    }
);

Распространение успеха и ошибки

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

Рассмотрим следующую гипотетическую promise цепочку с тремя обещаниями, P1, P2 и P3. Каждый promise имеет обработчик успеха и обработчик ошибок, поэтому S1 и E1 для P1, S2 и E2 для P2 и S3 и E3 для P3:

xhrCall()
  .then(S1, E1) //P1
  .then(S2, E2) //P2
  .then(S3, E3) //P3

В нормальном потоке вещей, где нет ошибок, приложение будет работать через S1, S2 и, наконец, S3. Но в реальной жизни все не так гладко. P1 может обнаружите ошибку, или P2 может столкнуться с ошибкой, вызвав E1 или E2.

Рассмотрим следующие случаи:

• Мы получили успешный ответ от сервера в P1, но возвращенные данные не правильно, или на сервере нет данных (например, пустой массив). В таком В этом случае для следующего обещания P2 он должен вызвать обработчик ошибок E2.

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

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

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

Если, с другой стороны, мы хотим вызвать обработчик ошибок для следующего обещания в цепочка, мы можем сделать это, используя объект deferred и вызывая его метод reject()

Теперь, что такое отложенный объект?

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

A deferred объект содержит promise объект. Через объект promise Вы можете указать, что должно произойти после завершения единицы работы. Вы сделать это, установив функции обратного вызова для объекта promise.

Отложенные объекты в Jquery: https://api.jquery.com/jquery.deferred/

Отложенные объекты в AngularJs: https://docs.angularjs.org/api/ng/service/$q

78 голосов
/ 17 декабря 2013

Функция then () связана с «обещаниями Javascript», которые используются в некоторых библиотеках или средах, таких как jQuery или AngularJS.

Обещание - это шаблон для обработки асинхронных операций. Обещание позволяет вам вызывать метод с именем «then», который позволяет вам указать функцию (ы) для использования в качестве обратных вызовов.

Для получения дополнительной информации см .: http://wildermuth.com/2013/8/3/JavaScript_Promises

А для угловых обещаний: http://liamkaufman.com/blog/2013/09/09/using-angularjs-promises/

30 голосов
/ 07 октября 2010

Насколько мне известно, в javascript (на момент написания этой статьи) нет встроенного then() метода.

Похоже, что все, что doSome("task") возвращаетимеет метод с именем then.

Если вы зарегистрируете результат возврата doSome() на консоль, вы сможете увидеть свойства того, что было возвращено.

console.log( myObj.doSome("task") ); // Expand the returned object in the
                                     //   console to see its properties.

ОБНОВЛЕНИЕ (Начиная с ECMAScript6) : -

Функция .then() включена в чистый javascript.

Из документации Mozilla здесь ,

Метод then () возвращает Promise.Он принимает два аргумента: функции обратного вызова для случаев успешного и неудачного выполнения Promise.

Объект Promise, в свою очередь, определяется как

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

То есть Promise действует как заполнитель для значения, которое еще не вычислено, но должнорешаться в будущем.А функция .then() используется для связывания функций, которые будут вызываться в Обещании, когда оно разрешено - либо как успех, либо как сбой.

13 голосов
/ 09 января 2018

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

doit().then(function() { log('Now finally done!') });
log('---- But notice where this ends up!');

// For pedagogical reasons I originally wrote the following doit()-function so that 
// it was clear that it is a promise. That way wasn't really a normal way to do 
// it though, and therefore Slikts edited my answer. I therefore now want to remind 
// you here that the return value of the following function is a promise, because 
// it is an async function (every async function returns a promise). 
async function doit() {
  log('Calling someTimeConsumingThing');
  await someTimeConsumingThing();
  log('Ready with someTimeConsumingThing');
}

function someTimeConsumingThing() {
  return new Promise(function(resolve,reject) {
    setTimeout(resolve, 2000);
  })
}

function log(txt) {
  document.getElementById('msg').innerHTML += txt + '<br>'
}
<div id='msg'></div>
5 голосов
/ 08 октября 2016

Вот небольшой JS_Fiddle.

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

Вы можете выполнить Обещание на нативном JavaScript: точно так же, как в jQuery есть обещания, каждое обещание может быть сложено, а затем может бытьвызывается с помощью обратных вызовов Resolve и Reject. Вот как вы можете связать асинхронные вызовы.

Я разветвлялся и редактировал документы MSDN в состоянии зарядки аккумулятора.

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

navigator
    .getBattery()
    .then(function(battery) {
       var charging = battery.charging;
       alert(charging);
    })
    .then(function(){alert("YeoMan : SINGH is King !!");});

Другой пример es6

function fetchAsync (url, timeout, onData, onError) {
    …
}
let fetchPromised = (url, timeout) => {
    return new Promise((resolve, reject) => {
        fetchAsync(url, timeout, resolve, reject)
    })
}
Promise.all([
    fetchPromised("http://backend/foo.txt", 500),
    fetchPromised("http://backend/bar.txt", 500),
    fetchPromised("http://backend/baz.txt", 500)
]).then((data) => {
    let [ foo, bar, baz ] = data
    console.log(`success: foo=${foo} bar=${bar} baz=${baz}`)
}, (err) => {
    console.log(`error: ${err}`)
})

Definition :: затем - метод, используемый для решения асинхронных обратных вызовов

, этовведено в ES6

Пожалуйста, найдите соответствующую документацию здесь Обещания Es6

5 голосов
/ 07 октября 2010

Я подозреваю, что doSome возвращает this, то есть myObj, который также имеет метод then. Стандартный метод сцепления ...

если doSome не возвращает это, будучи объектом, на котором был выполнен doSome, будьте уверены, что он возвращает некоторый объект с помощью метода then ...

как указывает @patrick, тогда нет () для стандартного js

1 голос
/ 27 апреля 2016

doSome ("задача") должна возвращать объект обещания, и это обещание всегда имеет функцию then. Так что ваш код такой же, как этот

promise.then(function(env) {
    // logic
}); 

и вы знаете, что это обычный вызов функции-члена.

1 голос
/ 21 июня 2013

Функция ".then ()" широко используется для обещанных объектов в программировании Asynchoronus для приложений Магазина Windows 8. Насколько я понял, это работает как обратный вызов.

Найти подробности в этом документе http://msdn.microsoft.com/en-us/library/windows/apps/hh700330.aspx

Конечно, это также может быть имя для любой другой определенной функции.

0 голосов
/ 07 октября 2010

В этом случае then() - это метод класса объекта, возвращаемый методом doSome().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...