【问题标题】:How to wait for a promise inside an each loop?如何在每个循环中等待一个承诺?
【发布时间】:2021-02-04 21:59:23
【问题描述】:

Promise 的新手 - 尝试找出逻辑。

我正在尝试自动抓取 youtube 预览缩略图,如 this answer 建议:

const youtubeAnimation = id => {
    return fetch(
        `https://cors-anywhere.herokuapp.com/https://www.youtube.com/results?search_query=${id}&sp=QgIIAQ%253D%253D`,
        { headers: {} }
    )
        .then(r => r.text())
        .then(html => {
            const found = html.match(
                new RegExp(`["|']https://i.ytimg.com/an_webp/${id}/(.*?)["|']`)
            );
            if (found) {
                try {
                    const url = JSON.parse(found[0]);
                    return url;
                } catch (e) {}
            }
            throw "not found";
        })
        .catch(e => {
            return false;
        });
};

我将 youtube ID 存储在视频属性的容器中,然后对页面上的单个视频执行此操作:

youtubeAnimation($('.video').attr('youtube')).then(function (value) {
    $('<img class="videopreview" src="' + value + '">').insertBefore($('.video'));
});

但我需要能够在页面上使用可变数量的$('.video') 元素来运行它。我试过把它放在每个循环中:

$(".video").each(function () {
    youtubeAnimation($(this).attr('youtube')).then(function (value) {
        $('<img class="videopreview" src="' + value + '">').insertBefore($(this));
    });
});

但这只是将预览缩略图添加到最后一个$('.video') 元素。使用 console.log 进行测试时,我可以看到所有预览图像都被发现,但只有最后一个图像应用于最后一个元素。在继续下一个元素之前,我需要以某种方式暂停 each 循环,直到 youtubeAnimation 完成它的工作。

要使这一切顺利进行,还需要哪些额外步骤?另外,答案将youtubeAnimation 作为常量而不是函数的原因是什么?

【问题讨论】:

  • 尝试.then((value) =&gt; 而不是.then(function (value) { - 所以this 是正确的
  • 顺便说一句,你不能像你想象的那样等待 .each 或 .forEach 中的 promise,即你不能使用 .forEach/.each 来执行一系列异步一个接一个的任务 - 只是想澄清你的问题不是等待承诺,它是 .then 中的 this 不是你所期望的
  • @JaromandaX 哇,它成功了! TIL 关于箭头函数。感谢您的洞察力,我要去研究了。如果问题是this,是否也可以使用常规函数并将$(this) 存储在变量中,然后在promise 中调用它?当我尝试时它不起作用。
  • 你是否像.each(function (value) { var $this = $(this); youtubeAnimation(... etc一样存储了$(this)
  • @JaromandaX 关闭,但我没有包括 varvalue 那里。它是.each(function () { this = $(this)...。我无法检查以确认是否可以解决问题,因为我现在受到速率限制。但是理论上,这应该是解决这个问题的另一种方式吧?

标签: javascript jquery promise youtube each


【解决方案1】:

我会尝试的一个选项是:

$(".video").each(async () => {
  const animation = await youtubeAnimation($(this).attr('youtube'));
  $('<img class="videopreview" src="' + value + '">').insertBefore($(this));
  
});

它利用箭头函数来保存this和async/await,使代码更具可读性。

【讨论】:

  • 谢谢,我也试过了。我认为第 3 行中的 value 应该是 animation?但是当我这样做时,我得到“无法读取属性'createDocumentFragment' of null”。
  • 如果你 .each(async function() { 这将起作用,因为你想要的 this.each 回调中的 this ...此代码中的 this 不正确跨度>
猜你喜欢
  • 2018-03-13
  • 2018-04-25
  • 2020-05-15
  • 2016-04-13
  • 2017-12-16
  • 2017-11-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-08
相关资源
最近更新 更多