JavaScript 中 FileReader 的 async/await 问题
Problem with async/await with FileReader in JavaScript
我在 Vue.js 项目中使用 FileReader,但我遇到以下代码问题:
async uploadDocuments(files) {
for (let file of files) {
let fileName = file.name;
let fileContent;
let reader = new FileReader();
reader.onload = async () => {
fileContent = reader.result;
await this.submitFile(fileContent, fileName, fileType)
.then(/* THEN block */)
.catch(/* CATCH block */);
};
reader.onerror = (error) => { console.warn(error); };
reader.readAsDataURL(file);
}
console.log("COMPLETED");
}
async submitFile(fileContent, fileName, fileType) {
// this function should handle the file upload and currently contains a timeout
await new Promise((resolve) => setTimeout(resolve, 3000));
}
这是所需的执行顺序(包含两个文件的示例):
- (等待 3 秒)
- THEN 块(文件 1)
- (等待 3 秒)
- THEN 块(文件 2)
- 完成
但这是实际的执行顺序:
- 完成
- (等待 3 秒)
- 然后块
- 然后块
“THEN 块”在超时后正确执行,但是 for
循环中的代码继续执行,而不等待 onload
函数的执行。
如何使 reader 异步?我尝试了很多解决方案(例如将 for
循环包装在一个承诺中并将 resolve()
函数放在 .then()
中)但其中 none 有效。
我建议“承诺”Reader 的东西然后使用 Promise.all
直到所有文件都上传。
uploadDocuments = async (event, files) => {
const filePromises = files.map((file) => {
// Return a promise per file
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async () => {
try {
const response = await this.submitFile(
reader.result,
file.name,
fileType
);
// Resolve the promise with the response value
resolve(response);
} catch (err) {
reject(err);
}
};
reader.onerror = (error) => {
reject(error);
};
reader.readAsDataURL(file);
});
});
// Wait for all promises to be resolved
const fileInfos = await Promise.all(filePromises);
console.log('COMPLETED');
// Profit
return fileInfos;
};
试试这个。
在 reader.onload
之前添加 await 它将保持到那时或 catch 块执行成功
async uploadDocuments(event) {
for (let file of files) {
let fileName = file.name;
let fileContent;
let reader = new FileReader();
await reader.onload = async () => {
fileContent = reader.result;
await this.submitFile(fileContent, fileName, fileType)
.then(/* THEN block */)
.catch(/* CATCH block */);
};
reader.onerror = (error) => { console.warn(error); };
reader.readAsDataURL(file);
}
console.log("COMPLETED");
}
async submitFile(fileContent, fileName, fileType) {
// this function should handle the file upload and currently contains a timeout
await new Promise((resolve) => setTimeout(resolve, 3000));
}```
我在 Vue.js 项目中使用 FileReader,但我遇到以下代码问题:
async uploadDocuments(files) {
for (let file of files) {
let fileName = file.name;
let fileContent;
let reader = new FileReader();
reader.onload = async () => {
fileContent = reader.result;
await this.submitFile(fileContent, fileName, fileType)
.then(/* THEN block */)
.catch(/* CATCH block */);
};
reader.onerror = (error) => { console.warn(error); };
reader.readAsDataURL(file);
}
console.log("COMPLETED");
}
async submitFile(fileContent, fileName, fileType) {
// this function should handle the file upload and currently contains a timeout
await new Promise((resolve) => setTimeout(resolve, 3000));
}
这是所需的执行顺序(包含两个文件的示例):
- (等待 3 秒)
- THEN 块(文件 1)
- (等待 3 秒)
- THEN 块(文件 2)
- 完成
但这是实际的执行顺序:
- 完成
- (等待 3 秒)
- 然后块
- 然后块
“THEN 块”在超时后正确执行,但是 for
循环中的代码继续执行,而不等待 onload
函数的执行。
如何使 reader 异步?我尝试了很多解决方案(例如将 for
循环包装在一个承诺中并将 resolve()
函数放在 .then()
中)但其中 none 有效。
我建议“承诺”Reader 的东西然后使用 Promise.all
直到所有文件都上传。
uploadDocuments = async (event, files) => {
const filePromises = files.map((file) => {
// Return a promise per file
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async () => {
try {
const response = await this.submitFile(
reader.result,
file.name,
fileType
);
// Resolve the promise with the response value
resolve(response);
} catch (err) {
reject(err);
}
};
reader.onerror = (error) => {
reject(error);
};
reader.readAsDataURL(file);
});
});
// Wait for all promises to be resolved
const fileInfos = await Promise.all(filePromises);
console.log('COMPLETED');
// Profit
return fileInfos;
};
试试这个。
在 reader.onload
之前添加 await 它将保持到那时或 catch 块执行成功
async uploadDocuments(event) {
for (let file of files) {
let fileName = file.name;
let fileContent;
let reader = new FileReader();
await reader.onload = async () => {
fileContent = reader.result;
await this.submitFile(fileContent, fileName, fileType)
.then(/* THEN block */)
.catch(/* CATCH block */);
};
reader.onerror = (error) => { console.warn(error); };
reader.readAsDataURL(file);
}
console.log("COMPLETED");
}
async submitFile(fileContent, fileName, fileType) {
// this function should handle the file upload and currently contains a timeout
await new Promise((resolve) => setTimeout(resolve, 3000));
}```