如何延迟函数直到 forEach 语句完成?

How to delay a function until after a forEach statement completes?

我目前正在使用 React 开发消息传递应用程序。目前,我正在努力确定一种延迟向聊天发布消息的主要功能的方法。

主要问题是使用 Cloudinary API,为了提交图片消息,我需要从 POST request.Thus 吐出的 url,我还需要将 postMessage 方法延迟到我的照片上传到 Cloudinary 数据库之后,并且 'temp' 数组收集了新生成的图像 urls。我的问题开始并且很可能结束于这样一个事实,即我无法确定延迟 postMessage 直到我的 forEach 语句完成的正确方法。

这是我的 handleSubmit 方法的代码:

const handleSubmit = async (event) => {
    event.preventDefault();

    const formElements = event.currentTarget.elements;
    const formData = new FormData();
    let temp = [];

    if (imagesSelected.length > 0) {
      imagesSelected.forEach((image) => {
        formData.append('file', image);
        formData.append('upload_preset', 'sendpics');
        
        instance.post('https://api.cloudinary.com/v1_1/dg7d5il8f/image/upload', formData )
        .then((res) => {
          temp.push(res.data.url);
        })
        .catch((err) => {
          console.log(err);
        });
      });

      const reqBody = {
        text: formElements.text.value,
        recipientId: otherUser.id,
        conversationId,
        sender: conversationId ? null : user,
        attachments: temp,
      };
          
      postMessage(reqBody);
    } else {
      const reqBody = {
        text: formElements.text.value,
        recipientId: otherUser.id,
        conversationId,
        sender: conversationId ? null : user,
        attachments: [],
      };
          
      postMessage(reqBody);
    }

    setText('');
    setImagesSelected(() => []);
  };

问题仍然存在于第一个 if 语句中,因为一旦 forEach 语句触发,postMessage 就会立即触发,甚至在 temp 有机会填充新的 url 值之前。如果整个问题本身以任何方式令人费解,我们深表歉意。如果我需要澄清我的问题,请发表评论。感谢任何 help/suggestions!

我想你需要等待 for-of loop
您的案例示例:

for (const image of imagesSelected) {
  //...
  try {
    const resp = await instance.post(
      "https://api.cloudinary.com/v1_1/dg7d5il8f/image/upload",
      formData
    );
    temp.push(resp.data.url);
  } catch (error) {
    console.log(error);
  }
}

另一种方法是将 forEach 替换为 map 并添加 Promise.all 正如评论中提到的 E. Shcherbo

不幸的是,如果每个元素都需要异步 运行,则不能使用标准 Array.forEach(callback) 方法,因为以下代码不会等待循环完成。

一个合适的方法是为每个数组元素创建一个 Promise 并等待它们解析。如果你的元素很少,你可以手工完成,或者如果它们太多或者根本没有硬编码,你可以用循环创建 Promise-array。

可能是这样:


let promiseArray = []

imagesSelected.forEach(item => {
  let p = new Promise((resolve, reject) => {
    // do your asynchronous stuff here
    instance.post(...

      // when you want the code to be "marked" as finished, run
      resolve(optionalReturnData)

      // when an error happens
      reject(optionalReason)
    ...
  })

  promiseArray.append(p)
})

// wait for the promises
Promise.all(imagesSelected).then(returnDataArray => {
  // now all promises have resolved and you can continue
  ...
  postMessage(...)
})

详情请参考mdn documentation