друзья. Недавно начал изучать Ноду, в качестве обучающего задания придумал написать асинхронный многопоточный парсер с ограничением кол-ва одновременных загрузок. В связи с этим вопрос: Почему данный код в первом случае выполняется правильно (т.е. асинхронно, результаты выдаются после прихода всех данных с апи), а во втором случае, с ограничением числа загрузок - в ответ возвращается массив промисов?
Вот рабочий пример:
const axios = require('axios');
//It works
async function go2() {
try {
console.time('1st');
const urls = [
{
'url': 'https://randomuser.me/api',
'method': 'get'
},
{
'url': 'https://uinames.com/api',
'method': 'get'
}];
var promises = await urls.map(async function (currentValue, index, array) {
return axios(currentValue);
});
// await all three promises to come back and destructure the result into their own variables
var array = await Promise.all(promises).catch(function(err) {
console.log(err.message); // some coding error in handling happened
});;
const results=array.map(function (currentValue, index, array) {
return currentValue.status;
});
console.log(results);
console.timeEnd('1st');
return results;
} catch (e) {
console.error(e); //
}
}
go2();
Вот нерабочий пример:
async function go3() {
try {
console.time('1st');
const MAX_SIMULTANEOUS_DOWNLOADS = 2;
const urls = [
{
'url': 'https://stats.nba.com/stats/teamyearbyyearstats?LeagueID=00&SeasonType=Playoffs&TeamID=1610612759&PerMode=PerGame',
'method':'get'
},
{
'url': 'https://api.github.com/users/wesbos',
'method':'get'
},
{
'url': 'https://randomuser.me/api',
'method':'get'
},
{
'url': 'https://uinames.com/api',
'method':'get'
}
];
let subarray = []; //массив в который будет выведен результат.
// Разбиваем массив на чанки, чтобы сразу все ссылки не грузить за один заход
for (let i = 0; i <Math.ceil(urls.length/MAX_SIMULTANEOUS_DOWNLOADS); i++){
subarray[i] = urls.slice((i*MAX_SIMULTANEOUS_DOWNLOADS), (i*MAX_SIMULTANEOUS_DOWNLOADS) + MAX_SIMULTANEOUS_DOWNLOADS);
}
//Здесь должен по идее сработать await, но нет.
var dataFromRequest =await subarray.map(async function (currentValue, index, array) {
var promises = await currentValue.map(async function (currentValue1, index1, array) {
return axios(currentValue1);
});
// await all three promises to come back and destructure the result into their own variables
var responses=await Promise.all(promises).catch(function(err) {
console.log(err.message); // some coding error in handling happened
});
const results=await responses.map(function (currentValue1, index1, array) {
console.log(index1, currentValue1.data); // some coding error in handling happened
return currentValue1.status;
});
return results;
});
console.log(dataFromRequest);
console.timeEnd('1st');
return dataFromRequest;
} catch (e) {
console.error(e); //
}
}
go3();
Ответ от сервера во втором случае:
[ Promise { }, Promise { } ]
await
должен применяться к Promise
.
map
- возвращает массив, поэтому нет смысла перед map
ставить await
.
Вместо этого, нужно передать его, например, в Promise.all
и уже к результату применить await
.
Правильный ответ дал Grundy - действительно оборачивание в Promise.all
помогло. На всякий случай показываю правильный вариант кода, вдруг кому пригодится:
async function go3() {
try {
console.time('1st');
const MAX_SIMULTANEOUS_DOWNLOADS = 2;
const urls = [
{
'url': 'https://stats.nba.com/stats/teamyearbyyearstats?LeagueID=00&SeasonType=Playoffs&TeamID=1610612759&PerMode=PerGame',
'method':'get'
},
{
'url': 'https://api.github.com/users/wesbos',
'method':'get'
},
{
'url': 'https://randomuser.me/api',
'method':'get'
},
{
'url': 'https://uinames.com/api',
'method':'get'
}
];
let subarray = []; //массив в который будет выведен результат.
// Разбиваем массив на чанки, чтобы сразу все ссылки не грузить за один заход
for (let i = 0; i <Math.ceil(urls.length/MAX_SIMULTANEOUS_DOWNLOADS); i++){
subarray[i] = urls.slice((i*MAX_SIMULTANEOUS_DOWNLOADS), (i*MAX_SIMULTANEOUS_DOWNLOADS) + MAX_SIMULTANEOUS_DOWNLOADS);
}
var dataFromRequest = await Promise.all(subarray.map(async function (currentValue, index, array) {
var promises = currentValue.map(async function (currentValue1, index1, array) {
return axios(currentValue1);
});
// await all three promises to come back and destructure the result into their own variables
var responses = await Promise.all(promises).catch(function (err) {
console.log(err.message); // some coding error in handling happened
});
const results = responses.map(function (currentValue1, index1, array) {
console.log(index1, currentValue1.data); // some coding error in handling happened
return currentValue1.status;
});
return results;
})
);
console.log(dataFromRequest);
console.timeEnd('1st');
return dataFromRequest;
} catch (e) {
console.error(e); //
}
}
go3()
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Перевод документов на английский язык: Важность и ключевые аспекты
Начинаю изучать vue, возник вопрос, как данные из input введенные пользователем записать в массив namesThatRhyme, в виде value:введенные данные , тк сейчас...
Допустим, я написал функцию:
Как из такой строки с датой ddmm
перепробовал уже все методы, не могу остановить таймер на сервере nodejsПробовал разные варианты и с setInterval и setTimeout