javascript - 是否可以在 jQuery.each() 内部使用同步 promise sleep ?

标签 javascript jquery asynchronous promise each

基本上就是这样。我想在同步函数中使用 jQuery 的每个函数。 不过,据我所知。它不起作用,因为每个函数只是检查返回值是否为 false 以打破循环。它不会检查它是否是一个 promise ,然后将其设置为等待它得到解决。有没有一种简单的方法可以使 jQuery 的每个函数与 Promise 同步?

我目前有一个替代方案,即创建一个迭代元素的 for 循环,但写起来有点长,所以我想尽可能避免这种情况。

这是一个 fiddle : https://jsfiddle.net/3pcvqswn/2/

function sleep(ms)
{
    return new Promise(resolve => setTimeout(resolve, ms));
}

$(document).ready(function()
{
    (async () =>
  {
    console.log("This method works, but its lengthy to write");
    var elements = $("div");

    for(var index = 0; index < elements.length; index++)
    {
        var el = $(elements.eq(index));

        console.log("The content is: " + el.text());

      await sleep(1000);
        }

    console.log("This method doesn't work, but its easier to write");
    $("div").each(async (index, el) =>
    {
        console.log("The content is: " + $(el).text());

      // doesn't wait
      await sleep(1000);
    });
  })();
});

我决定使用 for of,但同时具有索引和元素回调的更准确的解决方案是

  Object.entries($("div")).forEach(async ([index, el]) =>
  {
    console.log("row ", index, el);
  });

最佳答案

否 - jQuery 的 .each 的工作方式与 forEach 类似。每个回调都会被一个接一个地触发,如果回调返回一个 Promise(例如,如果它是一个异步函数),则不会等待它 - 它的工作方式类似于

callback();
callback();
callback();

除非回调中的某些内容阻塞(如果您使用良好的编程实践,则不应出现这种情况),回调中的任何异步初始化都不会导致进一步的回调等待该异步操作完成.

但是 jQuery 对象是可迭代的,因此使用简洁的 for..of 来迭代元素是很简单的:

const sleep = ms => new Promise(res => setTimeout(res, ms));

(async () => {
  for (const elm of $("div")) {
    console.log("The content is: " + $(elm).text());
    await sleep(1000);
  }
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>text 1</div>
<div>text 2</div>
<div>text 3</div>

在我看来,这一点也不冗长。

为了在循环中使用 await,循环必须是 for 循环(for..in、for..of 或 for( let i = ...),或者需要构造循环的迭代机制,以便等待最后一个回调解析,例如使用 reduce:

const sleep = ms => new Promise(res => setTimeout(res, ms));

[...$("div")].reduce(async (lastProm, elm) => {
  await lastProm;
  console.log("The content is: " + $(elm).text());
  await sleep(1000);
}, Promise.resolve());
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>text 1</div>
<div>text 2</div>
<div>text 3</div>

<小时/>

旁注几乎不值得一提 - 我之前说过在 .each 中使用 await 不起作用

Unless something in the callback blocks (which it shouldn't if you're using decent programming practices)

如果您编写了一个昂贵且愚蠢的阻塞版本的 sleep ,它会消耗所有资源直到到达下一秒,那么“可能”在循环内等待,但永远不应该这样做:

const sleep = ms => {
  const now = Date.now();
  while (Date.now() - now < ms) {}
}

正确使用 Promise 会更好。

关于javascript - 是否可以在 jQuery.each() 内部使用同步 promise sleep ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60592118/

相关文章:

javascript - 如何使用回调来保证顺序执行?

c# - 如何正确地使方法异步?

javascript - 正则表达式在第 n 次出现的字符处剪切字符串并返回字符串的第一部分

javascript - 使用 jquery 从列表中添加和删除类

所有输入的 jQuery 表单反序列化

javascript - <head> 中应包含哪些 JavaScript,<body> 中应包含哪些内容?

multithreading - 从函数返回后让 goroutines 保持运行

javascript - 如何保护 tcp 连接 - nodejs?

javascript - HTML Canvas 无法绘制图像

c# - 在 MVC 4 中保持和执行时间