如何延迟函数直到 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。
我目前正在使用 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。