在for循环中处理多个异步函数调用

时间:2020-03-04 22:44:18

标签: javascript reactjs asynchronous axios

我正在尝试执行多个异步操作:Axios请求位于for循环内。一切解决后,我想做点什么,但事情太多了,我不知道该怎么做。

我考虑过让Sourcer函数异步并在每次迭代中等待它(并将for循环包装在async函数中),但是一个问题是sourcer实际上不返回任何东西。我不知道如何从Axios的“ finally”子句中的sourcer返回。另一个问题是,我不想等待每个源程序调用,因为这会影响性能。

Promise。听起来似乎是正确的方向,但我不知道如何使用此for循环来实现它。

这是我的代码的相关部分(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 个答案:

答案 0 :(得分:1)

axios.get将返回一个Promise,因此只需建立Promise数组并使用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
    })
})