Рубрики
Без рубрики

Действительно понимание асинх / ждут

Понимание Async / ждут, узнав, как он работает за кулисами.

Автор оригинала: Rafael Vidaurre.

В этой статье я попробую Demystingify Async/await Узнав, что они на самом деле, и что на самом деле происходит за кулисами.

Вы знаете, что это делает, но вы знаете, как это делает?

У большинства разработчиков есть отношения в любви с JavaScript. Одной из причин для этого является то, что она стала жертвой одной из его лучших качеств: легко учиться, трудно освоить.

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

Эта разница проявляется в деталях и вызывает разочарование.

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

JavaScript не имеет классов – на самом деле, JavaScript использует прототипы, объекты Singleton, из которых другие объекты наследуют.

На самом деле все объекты в JavaScript имеют прототип, из которого они наследуют. Это означает, что «классы JavaScript» не ведут себя точно такими как классы.

Класс представляет собой план для создания объектных экземпляров, а прототип – это экземпляр объекта, что другие объектные экземпляры делегируют работу

Прототип не является план, он на самом деле существует, это там. Вот почему вы можете добавить новый метод для массива, и вдруг все массивы могут использовать его. Это можно сделать во время выполнения, влияя на уже инстанцированный объект.

var someArray = [1, 2, 3];
Array.prototype.newMethod = function() {
  console.log('I am a new method!');
};
someArray.newMethod(); // I am a new method!
// The above code would not be possible with real classes, because // modifying a blueprint does not modify whatever was built with it.

Короче говоря, классы в JavaScript являются синтаксический сахар для прототипа наследования.

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

Async/a ждать спецификации

Async-функции являются дополнением к языку, уже включенному в последнем проекте ECMAScript (Stage 4). Вы можете использовать их сегодня, используя транспортер Babel.

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

За прошедшие годы у нас были несколько способов борьбы с асинхронным, не сходящимся с ума. Для большей части жизни JavaScript мы полагались на обратные вызовы:

setTimeout(function() {
  console.log('This runs after 5 seconds');
}, 5000);
console.log('This runs first');

Обратные вызовы хорошие и все, но что, если мы должны делать это последовательно?

doThingOne(function() {
  doThingTwo(function() {
    doThingThree(function() {
      doThingFour(function() {
        // Oh no
      });
    });
  });
});

То, что вы видите выше, иногда называют пирамидой гибели или обратного вызова ада, а в их честь есть веб-сайты. Нехорошо.

Вот: обещания

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

function buyCoffee() {
  return new Promise((resolve, reject) => {
    asyncronouslyGetCoffee(function(coffee) {
      resolve(coffee);
    });
  });
}

BuyCoffee возвращает обещание, которое представляет процесс покупки кофе. Функция разрешения сигнализирует о том, что он закончил. Он получает значение в качестве аргумента, который будет доступен через обещание позже.

Экземпляр обещания имеет два основных метода:

  • Тогда : Это запускает обратный вызов, который вы передаете ему, когда обещание закончилось
  • поймать : Это запускает обратный вызов, который вы передаете к нему, когда что-то пошло не так, что вызвало обещание отказаться от разрешения.

Отклонить либо вручную (например, мы выполняем вызов ajax и получили ошибку сервера), либо его называют автоматически, если uncaught исключение брошено внутри кода обещания.

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

Это может быть чрезвычайно расстраивающим, поэтому избегайте ситуации на всех расходах.

Обещания имеют некоторые другие очень интересные свойства, которые позволяют им быть цепочкой. Допустим, у нас есть другие функции, которые возвращают обещание. Мы могли бы сделать это:

buyCoffee()
  .then(function() {
    return drinkCoffee();
  })
  .then(function() {
    return doWork();
  })
  .then(function() {
    return getTired();
  })
  .then(function() {
    return goToSleep();
  })
  .then(function() {
    return wakeUp();
  });

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

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

Они сделают это с возвращенной стоимостью возвращенного обещания (вздох, извините, я не могло сказать что лучше).

… Пример к спасению!

const firstPromise = new Promise(function(resolve) {
  resolve("first");
});
const secondPromise = new Promise(function(resolve) {
  resolve("second");
});
const doAllThings = firstPromise.then(function() {
  return secondPromise;
});
doAllThings.then(function(result) {
  console.log(result); // This logs: "second"
});

Хорошо, мы почти там, я обещаю. (каламбур нерешенные).

Async-функции – это функции, которые возвращают обещания

Верно. Это причина, по которой я потратил время, чтобы кратко объяснить обещания, потому что действительно понять Async/await , вам нужно знать, насколько обещания работают, как правильно понять классы в JavaScript, вам нужно понять прототип.

Как это работает

  • Есть асинхронные функции. Они объявлены, представляя слово async В их декларации: Async Function DoAsyncStuff () {... Код} Отказ
  • Ваш код может быть приостановлен в ожидании асинхронизации с ждут/
  • ждут, что возвращает любую функцию Async, когда это сделано.
  • ждут можно использовать только внутри асинхронизации.
  • Если функция ASYNC бросает исключение, исключение будет пузым на родительские функции, как в обычном JavaScript, и его можно поймать с попробуйте/поймать Отказ

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

Это означает, что вы всегда должны использовать попробуйте/поймать Везде, где начинается цепочка вызовов функций async. Это хорошая практика, чтобы всегда иметь одну попытку/поймать на цепочку, если только не делает это абсолютно необходимо. Это обеспечит одно место для решения ошибок при выполнении Async Works и заставит вас правильно цепочить ваши вызовы функций Async.

Давайте посмотрим на какой-код

// Some random async functions that deal with value
async function thingOne() { ... }
async function thingTwo(value) { ... }
async function thingThree(value) { ... }
async function doManyThings() {
  var result = await thingOne();
  var resultTwo = await thingTwo(result);
  var finalResult = await thingThree(resultTwo);
  return finalResult;
}
// Call doManyThings()

Вот как код с Async/await выглядит как. Он очень близко к синхронному коду, а синхронный код гораздо проще понять.

Итак, так как Домашниение () Является ли асинхронная функция тоже, как мы ждете? Мы не можем. Не с нашим новым синтаксисом. У нас есть три варианта:

  • Пусть остальная часть нашего кода выполняется и не жди его до конца, что мы могли бы даже хотеть во многих случаях.
  • Позвоните в другой асинхронный функцию, завернутый с попробуйте/поймать блок или …
  • Используйте это как обещание.
// Option 1:
doManyThings();
// Option 2:
(async function() {
  try {
    await doManyThings();
  } catch (err) {
    console.log(err);
  }
})();
// Option 3:
doManyThings().then((result) => {
  // Do the things that need to wait for our function
}).catch((err) => {
  throw err;
});

Опять же, они функционируют, что возвращает обещания

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

Простая асинхронная функция:

// Async/Await version
async function helloAsync() {
  return "hello";
}
// Promises version
function helloAsync() {
  return new Promise(function (resolve) {
    resolve("hello");
  });
}

Async-функция, которая ждет другого результата функции ASYNC:

// == Async/Await version ==
async function multiply(a, b) {
  return a * b;
}
async function foo() {
  var result = await multiply(2, 5);
  return result;
}
(async function () {
  try {
    var result = await foo();
    console.log(result); // Logs 5
  }
  catch(err) {
    console.log(err);
  }
})();
// == Promises version ==
function multiply(a, b) {
  return new Promise(function (resolve) {
    resolve(a * b);
  });
}
function foo() {
  return new Promise(function(resolve) {
    multiply(2, 5).then(function(result) {
      resolve(result);
    });
  );
}
new Promise(function() {
  foo().then(function(result) {
    console.log(result); // Logs 5
  }).catch(function(err) {
    throw err;
  });
});

Обратите внимание, что вышеупомянутое использование обещаний не рекомендуется, я просто сформировал их таким образом, чтобы было легче использовать для сравнения против примеров Async/await.

Обертывание

Я надеюсь, что это немного очищает картину. Async/await Легко, пока вы хорошо понимаете обещания.

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