Я застрял в асинхронном программировании на Javascript. Я знаю, что Promise.all() будет работать параллельно.
Не могли бы вы сказать мне, что я не так с этим кодом ниже?
Это должно занять 100ms
. А на самом деле нужно 200ms
:(
// 1. Define function here
var getFruit = async (name) => {
const fruits = {
pineapple: ":pineapple:",
peach: ":peach:",
strawberry: ":strawberry:"
};
await fetch('https://jsonplaceholder.typicode.com/photos'); // abount 100ms
return fruits[name];
};
var makeSmoothie = async () => {
const a = getFruit('pineapple');
const b = getFruit('strawberry');
const smoothie = await Promise.all([a, b]);
return smoothie;
//return [a, b];
};
/// 2. Execute code here
var tick = Date.now();
var log = (v) => console.info(`${v} \n Elapsed: ${Date.now() - tick}`);
makeSmoothie().then(log);
@TangentiallyPerpendicular нет, await в getFruit
не блокирует параллельный getFruit
вызов, который вызывает Promise.all
.
@Nilesh Patel Мне просто нужно какое-то обещание, чтобы измерить, а также определить, работает ли Promise.all
правильно или нет. Особенно, что я не так с методом getFruit()
.
Ваша логика в порядке, она работает максимально параллельно со стороны клиента.
Вы можете проверить это, дождавшись setTimeout
вместо выборки:
await new Promise(resolve => setTimeout(resolve, 100));
Возможно, сайт-заполнитель ставит соединения в очередь на своей стороне или что-то в этом роде. В любом случае вы должны измерять что-то предсказуемое, а не сеть.
Редактировать:
Просто чтобы объяснить немного больше, что не поместится в комментарии.
Давайте поместим мой трюк с ожиданием в реальную функцию:
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
Хорошо, теперь вы бы назвали это как await wait(100)
. Теперь для сравнения:
await wait(100)
await fetch(...)
С точки зрения настройки вашего кода, они одинаковы. Они выполняют некоторую асинхронную задачу, которая занимает около 100 мс и возвращает результат. Если бы Promise.all()
не выполнял это параллельно, версия wait(100)
определенно заняла бы 200 мс или больше.
fetch
не такой надежный тест, как setTimeout
, потому что он работает по сети. Есть много вещей, которые вы не можете контролировать с помощью этого звонка, например:
Не совсем ясно, что именно вызывает здесь очевидное синхронное поведение. Возможно, вы найдете какие-то ответы в сетевой панели. Но с точки зрения кода вам больше нечего делать. Он доказуемо распараллелен с тестом setTimeout
, который гораздо более надежен как тест, поскольку это просто локальный таймер.
Привет, братан, не мог бы ты сказать мне, почему мой fetch() не работает параллельно? А чем отличаются ваши fetch()
и await new Promise
?
@Phong Он уже сказал вам, почему ваша выборка не работает параллельно. Fetch может работать параллельно, но он предполагает, что https://jsonplaceholder.typicode.com
обслуживает запросы последовательно. Почему jsonplaceholder.typicode.com
не отвечает параллельно, может быть из-за многих вещей: все браузеры имеют ограничение на подключение к каждому IP-адресу, поэтому вы можете достичь этого ограничения (помните, запросы браузера иногда генерируют два запроса — запрос OPTION для CORS, а затем реальные запросы GET, которые могут быть двумя соединениями), сам веб-сайт может иметь ограниченную пропускную способность и т. д.
Попробуйте запросить 100 изображений вместо 2. Некоторые серверы и маршрутизаторы увеличивают пропускную способность при ответе с большим количеством данных. Почему некоторое сетевое оборудование и серверы спроектированы таким образом? Таким образом, они могут одинаково быстро обслуживать многих клиентов, а не одного клиента.
Спасибо @slebetman и @Matt. Это решено. Кстати, что произойдет, если я изменю await fetch()
или await wait(100)
блокировщиком кода, как это loop from 1 to 2000
. Это становится синхронизацией, верно? В итоге Promise.all()
не работают параллельно?
@Phong правильно, Promise.all
может планировать только асинхронные задачи параллельно. Он не может преобразовать синхронный цикл ЦП в отдельный поток или что-то еще. fetch
по своей природе асинхронный, поэтому его вообще можно запланировать с помощью Promise.all
API возвращает список фотографий, и вы пытаетесь получить фрукты ... как они связаны?