Автор: д-р Аксель Раушмайер Переводчик: Front-end Xiaozhi Источник: 2ality
Ставь лайк и смотри, поиск в WeChat【Переезд в мир】Обратите внимание на этого человека, который не имеет большого фабричного прошлого, но имеет восходящий и позитивный настрой. эта статья
GitHub
GitHub.com/QQ449245884…Он был включен, статьи были классифицированы, и многие мои документы и учебные материалы были систематизированы.
Все говорили, что нет проекта для написания резюме, поэтому я помог вам найти проект, и это было с бонусом.【Учебник по строительству】.
Начиная с ES6, мы в основном используемPromise.all()
а такжеPromise.race()
,Promise.allSettled()
Предложение достигло стадии 4, поэтому оно будетECMAScript 2020
часть.
1 Обзор
Promise.all(promises: Iterable<Promise>): Promise<Array>
-
Promise.all(iterable)
метод возвращаетPromise
экземпляр, этот экземпляр находится вiterable
все параметрыpromise
"разрешены" или не включены в параметрpromise
Когда обратный вызов завершается (разрешить); если параметрpromise
Произошел сбой (отклонен), обратный вызов этого экземпляра не удался (отклонен), причиной сбоя является первый сбойpromise
результат
Promise.race(promises: Iterable<Promise>): Promise
-
Promise.race(iterable)метод возвращает
promise
, как только один из итераторовpromise
разрешено или отклонено, возвращеноpromise
будут решены или отклонены.
Promise.allSettled(promises: Iterable<Promise>): Promise<Array<SettlementObject>>
- Метод **Promise.allSettled()** возвращает
promise
,Долженpromise
во всех данныхpromise
анализируется после того, как он был проанализирован или отклонен, и каждый объект описывает каждыйpromise
результат.
Резюме: статус обещания
с учетом возвращенияPromise
асинхронные операции, следующиеPromise
возможные состояния:
- pending: начальное состояние, ни состояние успеха, ни состояние отказа.
- выполнено: означает, что операция завершена успешно.
- отклонено: означает, что операция не удалась.
- Урегулировано:
Promise
Либо завершено, либо отклонено.Promise
Однажды достигнутое, его состояние никогда не меняется.
3. Что такое комбинация
Также известный как шаблон «часть-целое», он объединяет объекты в древовидную структуру для представления иерархии «часть-целое». Шаблон композиции делает использование отдельных объектов и объектов композиции согласованным и основан на двух функциях:
- Примитивные функции (сокращенно примитивы) создают атомарные блоки.
- Композиционная функция (сокращенно: композиция) объединяет атомы и/или композиты в композит.
Для обещаний JS
-
К примитивным функциям относятся:
Promise.resolve()
,Promise.reject()
-
Объединение функций:
Promise.all()
,Promise.race()
,Promise.allSettled()
4. Promise.all()
Promise.all()
Сигнатура типа:
- Promise.all(promises: Iterable<Promise>): Promise<Array>
Ситуация возврата:
Выполнение:Если переданный в iterable пустой,Promise.all
синхронно вернет завершенный (resolved
) положение делpromise
.
Если все входящиеpromise
становятся полными, или переданный в iterable не содержитpromise
,Promise.all
вернутьpromise
Становится полным асинхронно.
При любых условиях,Promise.all
вернутьpromise
Результатом статуса завершения является массив, который содержит все значения, переданные в объект параметра итерации (в том числе не обещанные значения).
Отказ/отказ:Если входящийpromise
один неудачник(rejected
),Promise.all
Асинхронно отправляет результат сбоя в функцию обратного вызова состояния сбоя, независимо от другихpromise
завершено.
Вот пример:
const promises = [
Promise.resolve('a'),
Promise.resolve('b'),
Promise.resolve('c'),
];
Promise.all(promises)
.then((arr) => assert.deepEqual(
arr, ['a', 'b', 'c']
));
Что делать, если одно из обещаний отклонено:
const promises = [
Promise.resolve('a'),
Promise.resolve('b'),
Promise.reject('ERROR'),
];
Promise.all(promises)
.catch((err) => assert.equal(
err, 'ERROR'
));
Описание рисунка нижеPromise.all()
как это работает
4.1 Асинхронный .map() и Promise.all()
методы преобразования массива, такие как.map()
,.filter()
д., для синхронных вычислений. Например
function timesTwoSync(x) {
return 2 * x;
}
const arr = [1, 2, 3];
const result = arr.map(timesTwoSync);
assert.deepEqual(result, [2, 4, 6]);
если.map()
Обратный вызов основан наPromise
Что происходит с функцией ? использовать этот путь.map()
Возвращаемый результат представляет собойPromises
множество.
Promises
Массивы не являются данными, которые может использовать обычный код, но мы можемPromise.all()
для решения этой проблемы: он преобразует массив Promises вPromise
и реализуется с использованием массива простых значений.
function timesTwoAsync(x) {
return new Promise(resolve => resolve(x * 2));
}
const arr = [1, 2, 3];
const promiseArr = arr.map(timesTwoAsync);
Promise.all(promiseArr)
.then(result => {
assert.deepEqual(result, [2, 4, 6]);
});
Более практический рабочий пример с .map()
Далее мы используем.map()
а такжеPromise.all()
отWeb
загрузить файл. Во-первых, нам понадобятся следующие вспомогательные функции:
function downloadText(url) {
return fetch(url)
.then((response) => { // (A)
if (!response.ok) { // (B)
throw new Error(response.statusText);
}
return response.text(); // (C)
});
}
downloadText()
использовать на основеPromise
Fetch API загружает файлы в виде потока строк:
-
Во-первых, он получает ответ асинхронно (строка A).
-
response.ok (строка B) проверяет наличие ошибок типа «файл не найден».
-
Если ошибок нет, используйте
.text()
(Строка C) Получить содержимое файла в виде строки.
В примере ниже мы скачали два файла
const urls = [
'http://example.com/first.txt',
'http://example.com/second.txt',
];
const promises = urls.map(
url => downloadText(url));
Promise.all(promises)
.then(
(arr) => assert.deepEqual(
arr, ['First!', 'Second!']
));
Упрощенная реализация Promise.all()
function all(iterable) {
return new Promise((resolve, reject) => {
let index = 0;
for (const promise of iterable) {
// Capture the current value of `index`
const currentIndex = index;
promise.then(
(value) => {
if (anErrorOccurred) return;
result[currentIndex] = value;
elementCount++;
if (elementCount === result.length) {
resolve(result);
}
},
(err) => {
if (anErrorOccurred) return;
anErrorOccurred = true;
reject(err);
});
index++;
}
if (index === 0) {
resolve([]);
return;
}
let elementCount = 0;
let anErrorOccurred = false;
const result = new Array(index);
});
}
##5. Promise.race()
Promise.race()
Определение метода:
Promise.race(promises: Iterable<Promise>): Promise
Promise.race(iterable)метод возвращаетpromise
, как только один из итераторовpromise
разрешено или отклонено, возвращеноpromise
будут решены или отклонены. Вот несколько примеров:
const promises = [
new Promise((resolve, reject) =>
setTimeout(() => resolve('result'), 100)), // (A)
new Promise((resolve, reject) =>
setTimeout(() => reject('ERROR'), 200)), // (B)
];
Promise.race(promises)
.then((result) => assert.equal( // (C)
result, 'result'));
вA
Ряд,Promise
является состоянием завершения, поэтому первыйC
Гильдия выполнит (хотя первыйB
строка отклонена).
Давайте посмотрим, что произойдет, если обещание будет отклонено первым:
const promises = [
new Promise((resolve, reject) =>
setTimeout(() => resolve('result'), 200)),
new Promise((resolve, reject) =>
setTimeout(() => reject('ERROR'), 100)),
];
Promise.race(promises)
.then(
(result) => assert.fail(),
(err) => assert.equal(
err, 'ERROR'));
Обратите внимание, что из-заPromse
был отвергнут первым, поэтомуPromise.race()
вернул отклоненныйPromise
это означаетPromise.race([])
Результат никогда не завершается.
На рисунке ниже показаноPromise.race()
Как это работает:
Promise.race(), когда время обещания истекает
В этом разделе мы будем использоватьPromise.race()
для обработки тайм-аутовPromise
. Следующие вспомогательные функции:
function resolveAfter(ms, value=undefined) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(value), ms);
});
}
resolveAfter()
Главное вернуть статус какresolve
изPromise
, значение - входящийvalue
Вызовите вышеуказанный метод:
function timeout(timeoutInMs, promise) {
return Promise.race([
promise,
resolveAfter(timeoutInMs,
Promise.reject(new Error('Operation timed out'))),
]);
}
timeout()
вернутьPromise
,ДолженPromise
Состояние зависит от входящегоpromise
условие .
вtimeout
в функцииresolveAfter(timeoutInMs, Promise.reject(new Error('Operation timed out'))
,пройти черезresolveAfter
Как видно из определения, возвращаемый результат имеет отклоненный статус.Promise
.
посмотри сноваtimeout(timeoutInMs, promise)
операции. Если входящийpromise
Когда статус завершен до указанного времени,timeout
Возвращаемый результат - завершенный статусPromise
, в состоянии пройти.then
Первый параметр обратного вызова обрабатывает возвращаемый результат.
timeout(200, resolveAfter(100, 'Result!'))
.then(result => assert.equal(result, 'Result!'));
И наоборот, если это делается после указанного времени, простоtimeout
Возвращаемый результат - статус отклоненияPromise
, что вызываетcatch
Функция обратного вызова, указанная методом.
timeout(100, resolveAfter(2000, 'Result!'))
.catch(err => assert.deepEqual(err, new Error('Operation timed out')));
Важно понимать, что на самом деле означает «Тайм-аут обещания»:
- Если входящий
Promise
Если это разрешено, результат будет возвращен вPromise
. - Если решение не будет решено достаточно быстро, вывод
Promise
Статус Отказано.
То есть тайм-аут блокирует только входящие промисы, влияя на выходные промисы (поскольку промисы могут быть разрешены только один раз), но не блокирует входящие промисы.Promise
асинхронная работа.
5.2 Упрощенная реализация Promess.race ()
Ниже приведеныPromise.race()
Упрощенная реализация (не выполняет проверки безопасности)
function race(iterable) {
return new Promise((resolve, reject) => {
for (const promise of iterable) {
promise.then(
(value) => {
if (settlementOccurred) return;
settlementOccurred = true;
resolve(value);
},
(err) => {
if (settlementOccurred) return;
settlementOccurred = true;
reject(err);
});
}
let settlementOccurred = false;
});
}
6.Promise.allSettled()
“Promise.allSettled”
Эта особенность обусловленаJason Williams,Robert Pamelyа такжеMathias Bynensпредложить.
promise.allsettle()
Определение метода:
- Promise.allSettled(promises: Iterable<Promise>) : Promise<Array<SettlementObject>>
он возвращаетArray
изPromise
, элементы которого имеют следующие характеристики типа:
type SettlementObject<T> = FulfillmentObject<T> | RejectionObject;
interface FulfillmentObject<T> {
status: 'fulfilled';
value: T;
}
interface RejectionObject {
status: 'rejected';
reason: unknown;
}
Promise.allSettled()
Метод возвращает обещание, которое разрешается после того, как все заданные обещания были разрешены или отклонены, и каждый объект описывает результат каждого обещания.
Например, например, каждый пользователь одновременно заполняет три отдельные формы на странице.Эти три формы отправляются на сервер в трех интерфейсах.Три интерфейса независимы и не имеют зависимости от порядка.На данный момент нам нужно дождаться завершения всех запросов Ситуация с запросом пользователя на отправку формы
в несколькихpromise
В то же время мы скоро подумаем об использованииPromise.all
для упаковки, но из-заPromise.all
Функция короткого замыкания , если какая-либо из трех отправок не удалась, последующая форма не будет отправлена, что не соответствует нашим потребностям.
Promise.allSettled
а такжеPromise.all
Точно так же его параметр принимаетPromise
массив , возвращает новыйPromise
, отличие только в том, что он не закорачивает, т.е.Promise
После того, как вся обработка завершена, мы можем получить каждыйPromise
статус, независимо от того, был он успешно обработан или нет.
Описание рисунка нижеpromise.allsettle()
как это работает
6.1 Пример Promise.allSettled()
ЭтоPromise.allSettled()
Быстрый демонстрационный пример использования
Promise.allSettled([
Promise.resolve('a'),
Promise.reject('b'),
])
.then(arr => assert.deepEqual(arr, [
{ status: 'fulfilled', value: 'a' },
{ status: 'rejected', reason: 'b' },
]));
6.2 Более сложный пример Promise.allSettled()
Этот пример похож на.map()
а такжеPromise.all()
Пример (который мы позаимствовали изdownloadText()
функция): мы загружаем несколько текстовых файлов,url
хранится в массиве. Однако на этот раз вместо остановки при ошибке мы хотим продолжить выполнение.Promise.allSettled()
Позвольте нам сделать это:
const urls = [
'http://example.com/exists.txt',
'http://example.com/missing.txt',
];
const result = Promise.allSettled(
urls.map(u => downloadText(u)));
result.then(
arr => assert.deepEqual(
arr,
[
{
status: 'fulfilled',
value: 'Hello!',
},
{
status: 'rejected',
reason: new Error('Not Found'),
},
]
));
6.3 Упрощенная реализация Promise.allSettled()
Этоpromise.allsettle()
Упрощенная реализация (без выполнения проверок безопасности)
function allSettled(iterable) {
return new Promise((resolve, reject) => {
function addElementToResult(i, elem) {
result[i] = elem;
elementCount++;
if (elementCount === result.length) {
resolve(result);
}
}
let index = 0;
for (const promise of iterable) {
// Capture the current value of `index`
const currentIndex = index;
promise.then(
(value) => addElementToResult(
currentIndex, {
status: 'fulfilled',
value
}),
(reason) => addElementToResult(
currentIndex, {
status: 'rejected',
reason
}));
index++;
}
if (index === 0) {
resolve([]);
return;
}
let elementCount = 0;
const result = new Array(index);
});
}
7. Характеристики короткого замыкания
Promise.all()
а такжеromise.race()
иметь характеристики короткого замыкания
-
Promise.all(): если параметр
promise
Произошел сбой (отклонен), обратный вызов этого экземпляра не выполнен (отклонен)
Promise.race(): если один из параметровpromise
Разрешено или отклонено, возвращенное обещание разрешено или отклонено.
8. Параллелизм и Promise.all()
8.1 Последовательное и параллельное выполнение
Рассмотрим следующий код:
asyncFunc1()
.then(result1 => {
assert.equal(result1, 'one');
return asyncFunc2();
})
.then(result2 => {
assert.equal(result2, 'two');
});
использовать.then()
Последовательное выполнение основано наPromise
функция: только еслиasyncFunc1()
выполняется после получения результатаasyncFunc2()
.
а такжеPromise.all()
выполняются одновременно
Promise.all([asyncFunc1(), asyncFunc2()])
.then(arr => {
assert.deepEqual(arr, ['one', 'two']);
});
9.2 Уловки параллелизма: сосредоточьтесь на том, когда начинаются операции
Советы по идентификации параллельного асинхронного кода: сосредоточьтесь на том, когда запускаются асинхронные операции, а не на том, как они обрабатываютсяPromises.
Например, каждая функция ниже выполняется одновременноasyncFunc1()
а такжеasyncFunc2()
, потому что они начинаются примерно в одно и то же время.
function concurrentAll() {
return Promise.all([asyncFunc1(), asyncFunc2()]);
}
function concurrentThen() {
const p1 = asyncFunc1();
const p2 = asyncFunc2();
return p1.then(r1 => p2.then(r2 => [r1, r2]));
}
С другой стороны, следующие две функции выполняются последовательноasyncFunc1()
а такжеasyncFunc2()
: asyncFunc2()
только приasyncFunc1()
вызывается только после разрешения решения.
function sequentialThen() {
return asyncFunc1()
.then(r1 => asyncFunc2()
.then(r2 => [r1, r2]));
}
function sequentialAll() {
const p1 = asyncFunc1();
const p2 = p1.then(() => asyncFunc2());
return Promise.all([p1, p2]);
}
9.3 Promise.all() и Fork-Join Программирование разделяй и властвуй
Promise.all()
Слабо связано с режимом параллелизма «форк-соединение». Вернемся к нашему предыдущему примеру:
Promise.all([
// (A) fork
downloadText('http://example.com/first.txt'),
downloadText('http://example.com/second.txt'),
])
// (B) join
.then(
(arr) => assert.deepEqual(
arr, ['First!', 'Second!']
));
- Вилка: в
A
line, разделяет две асинхронные задачи и выполняет их одновременно. - Присоединяйся
B
В строке суммируются результаты, полученные по каждой малой задаче.
Ошибки, которые могут существовать после развертывания кода, не могут быть известны в режиме реального времени.Чтобы решить эти ошибки впоследствии, много времени тратится на отладку журнала.Кстати, я рекомендую всем полезный инструмент мониторинга ошибок.Fundebug.
оригинал:2 али ненавидит.com/2019/08/pro…
общаться с
Статья постоянно обновляется каждую неделю. Вы можете выполнить поиск «Big Move to the World» в WeChat, чтобы прочитать и обновить ее как можно скорее (на одну или две статьи раньше, чем в блоге). Эта статья находится на GitHub.GitHub.com/QQ449245884…Он был включен, и многие мои документы были разобраны. Добро пожаловать в Звезду и совершенство. Вы можете обратиться в тестовый центр для ознакомления во время собеседования. Кроме того, обратите внимание на паблик-аккаунт и ответьте в фоновом режиме.Благосостояние, вы можете увидеть преимущества, вы знаете.