在Promise.all中读取多个文件不起作用



我正在尝试执行一些文件读取操作,如:

  1. 在Promise中读取包含用户信息的Excel文件。之后为了解决这个承诺,我会有一个用户数组
  2. 在第一个文件读取Promise的回调中,读取facePromise.all的Promise中用户的图像文件
  3. 使用Promise.all的原因是,我想读取异步文件。对于每个图像文件,我循环整个users数组来查找用户然后将人脸的Base64String结果存储到用户对象。然后用修改后的用户解析Promise
  4. 根据我的理解,如果没有一个承诺被拒绝。我应该在Promise.all的then回调中有一个Users数组,即我想要什么

但问题是,使用此代码Promise.all既不会被拒绝,也不会得到解决。在几乎没有修改的情况下,它在所有通过的个人承诺开始解决之前就得到了解决。

以下是执行文件读取的函数代码。

import { User } from "./types";
import * as XLSX from "xlsx";

// Loading users data from Excel Data... Id,Name,CardNo
export async function loadUsersData(usersFile: File) {
let result_users: User[] =await new Promise((resolve) => {
var reader = new FileReader();
reader.onload = function (e) {
const data = e.target.result;
const readedData = XLSX.read(data, { type: 'binary' });
const wsname = readedData.SheetNames[0];
const ws = readedData.Sheets[wsname];
/* Convert array to json*/
const parsedData = XLSX.utils.sheet_to_json(ws, { header: 1, blankrows: false });
parsedData.shift();
const users: User[] = parsedData.map((item: any) => {
const id = item[0].toString().trim();
const name = item[1].toString().trim();
const cardNo = item[2].toString().trim();
const user: User = { id, name, cardNo }; 
return user;
});
resolve(users);
}
reader.readAsBinaryString(usersFile)
});
return result_users;
}

//Loading Images of Users Faces to display in material table along with other user info
export async function loadUsersFaces(users: User[], facesList: FileList) {
const facesArray = Array.from(facesList)
const promises=facesArray.map(async face=>{
return await readFace(face, users);
})
let result_users: any=await Promise.all(promises);
return result_users
}
function readFace(face: File,users:User[]) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = function (e) {
let faceBase64String = e.target.result; //getting Base64String of image to render as custom column in material-table as https://material-table.com/#/docs/features/custom-column-rendering
users.map(user => {
if (face.name.includes(user.id) && face.name.includes(user.name)) {
let newUser={ ...user, face: faceBase64String };
console.log(`Resoling ${JSON.stringify(newUser)}`);
resolve(newUser);
}
})
}
reader.readAsDataURL(face)
});
}

下面是执行文件一个接一个读取的操作代码。

//Here is usersFile is an excel file Blob and FileList contain list of image files
export const loadUsers = (usersFile: File,faces: FileList) => (dispatch:Dispatch) => {
dispatch(actions.startCall({ callType: callTypes.list }));
usersService.loadUsersData(usersFile).then((users:any)=>{ // So far so good till this point.
usersService.loadUsersFaces(users,faces).then((users:any)=>{
console.log(users); // Here I should have users including Base64 Strings of face images in face property of User in the whole array of users 
dispatch(actions.usersFetched({ totalCount:users.length, entities:users }));
})
})
};

您没有正确处理来自文件读取器的错误,没有处理来自异步onload回调内代码的错误,最重要的是,您只是有条件地解析readFace函数中的promise(来自循环!(。

相反,您应该将其重构为一个单独的函数,用于文件读取器的承诺:

function readFile(file, method = 'readAsArrayBuffer') {
return new Promise((resolve, reject) => {
var reader = new FileReader();
reader.onload = e => resolve(e.target.result);
reader.onerror = reject;
reader[method](file);
});
}

现在您可以在不使用new Promise:的情况下编写其余代码

export async function loadUsersData(usersFile: File) {
const data = await readFile(usersFile, 'readAsBinaryString');
const readedData = XLSX.read(data, { type: 'binary' });
const wsname = readedData.SheetNames[0];
const ws = readedData.Sheets[wsname];
/* Convert array to json*/
const parsedData = XLSX.utils.sheet_to_json(ws, { header: 1, blankrows: false });
parsedData.shift();
const users: User[] = parsedData.map((item: any) => {
const id = item[0].toString().trim();
const name = item[1].toString().trim();
const cardNo = item[2].toString().trim();
const user: User = { id, name, cardNo }; 
return user;
});
return users;
}
async function readFace(face: File,users:User[]) {
const faceBase64String = await readFile(face, 'readAsDataURL');
for (const user of users) {
if (face.name.includes(user.id) && face.name.includes(user.name)) {
user.face = faceBase64String;
}
}
}

最新更新