在 JavaScript 中的 for 循环中调用异步函数

在 JavaScript 中,for 循环是最常见的迭代结构之一。然而,在 for 循环中调用异步函数时,可能会遇到一些问题。本文将介绍如何处理这些问题,并提供示例代码来说明如何使用 Promise 和 async/await 来优雅地解决这个问题。

问题描述

当我们在 for 循环中调用异步函数时,往往会面临以下两个主要问题:

  1. 异步函数的执行顺序可能不符合预期。
  2. 异步函数内部的变量作用域可能导致值被覆盖或者出现其他错误。

下面我们将分别介绍这两个问题以及如何解决它们。

问题一:异步函数的执行顺序

考虑下面的示例代码:

------- - - -- - - -- -----
  ------------- -- -
    --------------
  -- -----
-

我们期望输出的结果应该是:0, 1, 2, 3, 4。但是实际上输出的结果却是:5, 5, 5, 5, 5。

这是因为 setTimeout 是一个异步函数,会在 for 循环结束后才会执行。当 setTimeout 执行时,i 的值已经变成了 5,因此每次都输出了 5。

为了解决这个问题,我们需要在每次循环中保存当前的 i 值。可以使用闭包或者 let 关键字来实现:

-- ----
------- - - -- - - -- -----
  -------------
    ------------- -- -
      --------------
    -- -----
  -----
-

-- -- --- ---
------- - - -- - - -- -----
  --- - - --
  ------------- -- -
    --------------
  -- -----
-

问题二:异步函数内部的变量作用域

考虑下面的示例代码:

------- - - -- - - -- -----
  --- ------ - -------------
  --------------------
-

----- -------- -------------
  --- ---- - ----- ---------------------------------
  ------ -----
-

我们期望输出的结果是从 http://example.com/0http://example.com/4 的数据。但是实际上,输出的结果却是 5 次 undefined。

这是因为 fetchData 是一个异步函数,返回的是一个 Promise 对象,而不是直接返回数据。在 for 循环中执行 fetchData 时,它会立即返回 Promise 对象,并继续执行下一次循环。这样,for 循环结束后,Promise 对象才会被 resolve,输出的结果就是 5 次 undefined。

为了解决这个问题,我们需要使用 Promise 或者 async/await。下面是使用 Promise 的示例代码:

------- - - -- - - -- -----
  ------------------------ -- -
    --------------------
  --
-

-------- -------------
  ------ --- ----------------- ------- -- -
    ------------------------------------------ -- -
      --------------
    --
  --
-

下面是使用 async/await 的示例代码:

----- -------- -------
  ------- - - -- - - -- -----
    --- ------ - ----- -------------
    --------------------
  -
-

----- -------- -------------
  --- ---- - ----- ---------------------------------
  ------ -----
-

-------

结论

在 JavaScript 中的 for 循环中调用异步函数需要注意执行顺序和变量作用域问题。为了保证正确性,我们可以使用闭包或者 let 关键字来保存变量值,使用 Promise 或者 async/await 来解决执行顺序问题。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/26071