Работа с несколькими асинхронными вызовами функций в цикле for - PullRequest
0 голосов
/ 05 марта 2020

Я пытаюсь выполнить несколько асинхронных действий: Ax ios запросы внутри a для l oop. Я хочу сделать что-то после того, как все решено, но так много всего происходит, что я не знаю, как это сделать.

Я думал о том, чтобы сделать мою функцию sourcer асин c и ожидать ее на каждой итерации ( и обертывание for l oop в asyn c функцию), но одна проблема в том, что sourcer фактически ничего не возвращает. Я не знаю, как вернуться из sourcer из условия Ax ios «finally». Другая проблема заключается в том, что я не хочу ждать каждого вызова sourcer, потому что это повлияет на производительность.

Promise.all звучит как правильное направление, но я не знаю, как реализовать его с это для l oop.

Вот соответствующая часть моего кода (ts - большой массив объектов):

.then(ts => {
                // Create an association object that determines each media item's source
                const sourcer = media => { // Input is either [image filename, image url] or [image filename, image url, video filename, video url]
                    // Test to see if the original URL works
                    let validURL = true
                    axios.get(media[1])
                        .then(resp => {
                            if (resp.status.toString()[0] !== '2') validURL = false
                        })
                        .catch(resp => {
                            if (resp.status.toString()[0] !== '2') validURL = false
                        })
                        .finally(() => {
                            let newSources = JSON.parse(JSON.stringify(this.state.sources))
                            let newModals = JSON.parse(JSON.stringify(this.state.modals))
                            if (validURL) newSources[media[0]] = media[1]
                            // If the original URL does not work, pull media item from server
                            else newSources[media[0]] = `http://serveripaddress/get_media?filename=${media[0]}`
                            newModals[media[0]] = false
                            this.setState({ sources: newSources, modals: newModals })
                        })
                    if (media.length > 2) { // If the media item is a video, do the same checks
                        let validVURL = true
                        axios.get(media[3])
                            .then(resp => {
                                if (resp.status.toString()[0] !== '2') validVURL = false
                            })
                            .catch(resp => {
                                if (resp.status.toString()[0] !== '2') validVURL = false
                            })
                            .finally(() => {
                                let newSources2 = JSON.parse(JSON.stringify(this.state.sources))
                                let newThumbnails = JSON.parse(JSON.stringify(this.state.thumbnails))
                                if (validVURL) newSources2[media[2]] = media[3]
                                else newSources2[media[2]] = `http://serveripaddress/get_media?filename=${media[2]}`
                                newThumbnails[media[0]] = media[2] // Add an association for the video and its thumbnail
                                this.setState({ sources: newSources2, thumbnails: newThumbnails })
                            })
                    }
                }
                for (let t of ts) {
                    if (t.media) for (let m of t.media) sourcer(m)
                    if (t.preview_media) sourcer(t.preview_media)
                    if (t.video) sourcer(t.video)
                }
            })

Я хочу сделать что-то после итерации ts и все исходные вызовы завершены.

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

1 Ответ

1 голос
/ 05 марта 2020

axios.get вернет Promise, поэтому просто создайте свой массив из Promise s и используйте Promise.all

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

Как-то так будет работать. Я удалил ваш код, который обрабатывал ответ на каждый отдельный запрос get. Вы можете объединить этот код (или просто скопировать / вставить) туда, где я поместил заполнитель ниже:

.then(ts => {
    // Create an association object that determines each media item's source
    const sourcer = media => { // Input is either [image filename, image url] or [image filename, image url, video filename, video url]
        // Test to see if the original URL works
        let validURL = true;
        const promises = [];
        promises.push(axios.get(media[1]));
        if (media.length > 2) { // If the media item is a video, do the same checks
            let validVURL = true;
            promises.push(axios.get(media[3]));
        }
    }
    for (let t of ts) {
        if (t.media)
            for (let m of t.media) sourcer(m)
        if (t.preview_media) sourcer(t.preview_media)
        if (t.video) sourcer(t.video)
    }

    // Execute the Promises
    Promise.all(promises).then( results => {
        const media1 = results[0];
        const media3 = results[1];
        // TODO: Run your code for media1/media3 results
    })
})
...