【问题标题】:Javascript execute statement after fetch statements are completefetch 语句完成后的 Javascript 执行语句
【发布时间】:2020-11-21 22:39:32
【问题描述】:

在这里,我将 blob urls 存在于名为 imgs[] 的数组中转换为 base64 data,然后将 base 64 数据推送到名为 imgsPost[] 的数组中。 将所有 base64 数据推入数组后,我想在函数中使用该数组。

let imgsPost = [];
let imgs = ["bloburl1", "bloburl2", "bloburl3", "bloburl4"];
for (let i = 0; i < imgs.length; i++) {
    fetch(imgs[i].src)
        .then(res => {
            if (!res.ok) {
                throw Error(res.statusText);
            }
            return res.blob();
        })
        .then(data => {
            let tempBlob = data;
            let reader = new FileReader();
            reader.readAsDataURL(tempBlob);
            reader.onloadend = function () {
                let base64data = reader.result;
                imgsPost.push(base64data);
            }
        })
        .catch(error => {
            console.error('Error:', error);
        })
}
        //After all execution
        foo($imgsPost);

现在该函数首先使用一个空数组执行。所有其他代码都在运行。

【问题讨论】:

    标签: javascript image asynchronous promise fetch


    【解决方案1】:

    这是一个异步问题。您告诉 4 次执行一些代码在结果到达之后,然后您在结果到达之前执行foo($imgsPost);之前

    使用Promise.all的解决方案:

    const imgs = [
        'https://www.gravatar.com/avatar/5ac4d13d84719bf7f11cfd9ba7e0b15b?s=32&d=identicon&r=PG&f=1',
        'https://www.gravatar.com/avatar/f1f3cf96ee354f414ec58c2824f80938?s=32&d=identicon&r=PG&f=1'
    ];
    
    const promises = imgs.map(img => fetch(img)
        .then(res => {
            if (!res.ok) {
                throw Error(res.statusText);
            }
            return res.blob();
        })
        .then(data => {
            const reader = new FileReader();
            reader.readAsDataURL(data);
            return new Promise(resolve => reader.onloadend = () => resolve(reader));
        })
        .then(({ result }) => result)
    );
    
    const foo = console.log;
    
    Promise.all(promises).then(foo).catch(error => {
        console.error('Error: ', error);
    });

    您还可以使用async/await 语法,它提供了非常有用的语法糖而不是承诺,并使代码看起来像是同步的。

    【讨论】:

    • 在控制台记录 allRes 时,它显示 [undefined, undefined, undefined, undefined]。我尝试使用 return 1 而不是reader.result 但这也没有用。
    • 我在发帖前测试过了,你确定数组中包含有效的网址吗?
    • @SalilMittal 代码中有一个小错误:img.src 而不仅仅是img。我修复了它并将其发布为可运行代码。自己试试吧。
    • 如何使用 foo 作为函数(),参数作为数组?
    【解决方案2】:

    这是因为foo($imgsPost) 是同步的,并且在异步获取请求完成之前被调用。您可以尝试创建一堆 fetch 请求并将它们放入一个数组中,然后使用 Promise.all() 等待所有请求完成,然后再调用 foo()

    我不确定这是拼写错误还是只是一个示例,但您的 imgs 数组中没有 .src 属性。

    const imgs = ["bloburl1", "bloburl2", "bloburl3", "bloburl4"];
    const fetchRequests = imgs.map(img => {
        return fetch(img.src)
                  .then(res => {
                     if (!res.ok) {
                        throw Error(res.statusText);
                     }
                     return res.blob();
                    })
                   .then(data => {
                      let tempBlob = data;
                      let reader = new FileReader();
                      reader.readAsDataURL(tempBlob);
                      reader.onloadend = function () {
                      return reader.result;            
                    }
                })
                .catch(error => {
                    console.error('Error:', error);
                })
            }
    
       Promise.all(fetchRequests).then(allRes => foo(allRes))
    

    【讨论】:

    • 在控制台记录 allRes,它说 [undefined, undefined, undefined, undefined]
    • 这行不通,因为永远不会检索到 onloadend 回调的结果
    • 但是 foo 被作为 [undefined, undefined, undefined, undefined] 作为参数发送数组。我应该怎么做才能使数组具有base64字符串
    • @GuerricP 你能帮忙吗
    • 是的,对不起,我做了一些糟糕的复制和粘贴。但很高兴上面的答案为你整理好了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-26
    • 2021-06-04
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多