Реагируйте, отправьте несколько запросов в al oop и ждите - PullRequest
0 голосов
/ 29 апреля 2020

Я отправляю несколько запросов API, скажем "myapi / id". Мои идентификаторы могут варьироваться от [0..10000]. Поскольку отправка всех идентификаторов за один раз очень дорогая, я хотел бы отправить слайс в ожидании его получения и затем отправить следующий ломтик.

Вот код, который я использую:

async function getSlice(data) {
    let promises = []
    data.map((key) => {
        promises.push(fetch("myapi/"+key)
        .then(res => res.json())
        .then((result) => console.log(result))) //I want to store the result in an array
    }
    await Promise.all(promises)
} 

function getAll(data) {
    for(let i=0; i<= data.length; i+=10) {
        getSlice(data.slice(i,i+10));
        //I want to wait for the previous slice to complete before requesting for the next slice
    }
}

getAll(ids)

Однако запросы отправляются асинхронно / ожидания не происходит. Мне было интересно, есть ли ошибка в моем коде / есть ли способ отправить несколько запросов, используя для l oop, и дождаться их завершения, прежде чем отправлять следующие запросы.

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

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

Используя ваш способ (проще), он всегда будет ждать все, что нужно вернуть, затем проверяет, есть ли еще данные в массиве, и рекурсивно вызывает функцию снова или возвращает все, если это сделано. Надеюсь, это поможет.

async function getSlice(data) {
    let promises = []
    data.map((key) => {
        promises.push(fetch("myapi/"+key)
        .then(res => res.json())
        .then((result) => console.log(result))) //I want to store the result in an array
    }
    await Promise.all(promises)
} 

function getAll(data, index=0, length=10) {
    const allResponse = [];  
    return getSlice(data.slice(index,q)).then(response => {
        allResponse.push(response);
        newLength = length + 11 > data.length ? data.length : length + 11;
        if (index + 10 > data.length) //it's over
         return allResponse;
        return getAll(data, index + 10, length +11);
})}

Promise.all(getAll(ids).then(arrayResponse=>console.log('dowhatever',arrayResponse))
0 голосов
/ 01 мая 2020

Вам нужно использовать await перед async функцией, если вы хотите дождаться ее окончания sh

async function getAll(data) {
    for(let i=0; i<= data.length; i+=10) {
        await getSlice(data.slice(i,i+10));
    }
}

getAll(ids).then(()=>console.log('all data processed')).catch(err=>/*handle 
error*/)

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

 promises.push(fetch("myapi/"+key)
    .then(res => res.json())
    .then((result) => console.log(result))
    .catch((err)=>{/*handle error if needed*/; return null})

. После этого у вас будет несколько нулей в массиве с результатами

...