改进循环中的…以更快地使用Typescript

改进循环中的…以更快地使用Typescript,typescript,for-loop,asynchronous,Typescript,For Loop,Asynchronous,所以我被要求改进一个使用typescript中“for…in”的代码,以提高速度 这是原始代码: export interface AddressBook { emp_id: string | null; first: string; last: string; email: string; } export interface Payroll { emp_id: string; vacationDays: number; } interf

所以我被要求改进一个使用typescript中“for…in”的代码,以提高速度

这是原始代码:

    export interface AddressBook {
    emp_id: string | null;
    first: string;
    last: string;
    email: string;
}
export interface Payroll {
    emp_id: string;
    vacationDays: number;
}
interface Employee {
    id: string;
    name: string;
    startDate: Date;
    endDate: Date | null;
}
export interface EmailApi {
    sendEmail(email: string, subject: string, body: string): void;
}
function yearsSince(startDate: Date, endDate: Date): number {
    const millisecondsPerYear = 365 * 24 * 60 * 60 * 1000;
    return Math.trunc((endDate.getTime() - startDate.getTime()) / millisecondsPerYear);
}
/**
 * We haved decided to grant bonus vacation to every employee, 1 day per year of experience
 * we need to email them a notice.
 */

function grantVacation(
    emailApi: EmailApi,
    payroll: Payroll[],
    addresses: AddressBook[],
    employees: Employee[],
) {
    for (var index in payroll) {
        let payrollInfo = payroll[index];
        let addressInfo = addresses.find(x => x.emp_id == payrollInfo.emp_id);
        let empInfo = employees.find(x => x.id == payrollInfo.emp_id);
        let today = new Date();
        let yearsEmployed = 0;
        if (empInfo != undefined) {
            yearsEmployed = yearsSince(empInfo.startDate, today);
        }
        let newVacationBalance = yearsEmployed + payrollInfo.vacationDays;
        if (addressInfo != undefined && empInfo != undefined) {
            emailApi.sendEmail(
                addressInfo.email,
                "Good news!",
                `Dear ${empInfo.name}\n` +
                `based on your ${yearsEmployed} years of employment, you have been granted ${yearsEmployed} days of vacation, bringing your total to ${newVacationBalance}`
            );
        }
    }
    console.timeEnd();
}

// for the testing part I'll implement sendEmail as printing:
class myEmailApi implements EmailApi {
    sendEmail(email: string, subject: string, body: string): void {
        console.log('********************');
        console.log(`To ${email}, Subject: ${subject}, body: ${body}`);
        console.log('********************');
    }
}

let myPayroll: Payroll[] = [
    { emp_id: "1", vacationDays: 1 },
    { emp_id: "2", vacationDays: 2 },
    { emp_id: "3", vacationDays: 3 },
    { emp_id: "4", vacationDays: 4 },
    { emp_id: "5", vacationDays: 5 },
    { emp_id: "6", vacationDays: 6 }
];

let myAdress: AddressBook[] = [
    { emp_id: "1", first: "emp", last: "number 1", email: "emp1@gmail.com" },
    { emp_id: "2", first: "emp", last: "number 2", email: "emp2@gmail.com" },
    { emp_id: "3", first: "emp", last: "number 3", email: "emp3@gmail.com" },
    { emp_id: "4", first: "emp", last: "number 4", email: "emp4@gmail.com" },
    { emp_id: "5", first: "emp", last: "number 5", email: "emp5@gmail.com" },
    { emp_id: "6", first: "emp", last: "number 6", email: "emp6@gmail.com" },
];

let myEmployees: Employee[] = [
    { id: "1", name: "emp number 1", startDate: new Date("2020-01-01"), endDate: new Date("2025-01-01") },
    { id: "2", name: "emp number 2", startDate: new Date("2019-01-01"), endDate: new Date("2025-01-01") },
    { id: "3", name: "emp number 3", startDate: new Date("2018-01-01"), endDate: new Date("2025-01-01") },
    { id: "4", name: "emp number 4", startDate: new Date("2017-01-01"), endDate: new Date("2025-01-01") },
    { id: "5", name: "emp number 5", startDate: new Date("2016-01-01"), endDate: new Date("2025-01-01") },
    { id: "6", name: "emp number 6", startDate: new Date("2015-01-01"), endDate: new Date("2025-01-01") },
];

grantVacation(new myEmailApi(), myPayroll, myAdress, myEmployees);
这里没有什么特别的,这是一个演示,用于在计算员工的新假期后向公司的每位员工发送电子邮件

所以我已经读到,与其他循环(while、for、foreach)相比,使用“for…in”的速度非常慢,不应该使用,因为它对每个属性都使用了查找机制,这使得代码非常慢

我试图像这样改进代码(使用异步),但当我测量时间时,我发现两个版本有些相同,甚至更糟,这意味着我的解决方案至少没有提高性能

我的代码的改进版本是:

export interface AddressBook {
    emp_id: string | null;
    first: string;
    last: string;
    email: string;
}
export interface Payroll {
    emp_id: string;
    vacationDays: number;
}
interface Employee {
    id: string;
    name: string;
    startDate: Date;
    endDate: Date | null;
}
export interface EmailApi {
    sendEmail(email: string, subject: string, body: string): void;
}
function yearsSince(startDate: Date, endDate: Date): number {
    const millisecondsPerYear = 365 * 24 * 60 * 60 * 1000;
    return Math.trunc((endDate.getTime() - startDate.getTime()) / millisecondsPerYear);
}
/**
 * We haved decided to grant bonus vacation to every employee, 1 day per year of experience
 * we need to email them a notice.
 */

function calculateVacation(payrollInfo: Payroll, empInfo: Employee): Promise<any> {
    // "wrap" a sync function inside of a promise and finish the calulation.
    return new Promise((resolve) => {
        let today = new Date();
        let yearsEmployed = 0;

        if (empInfo != undefined) {
            yearsEmployed = yearsSince(empInfo.startDate, today);
        }
        let newVacationBalance = yearsEmployed + payrollInfo.vacationDays;
        // return all the relevant values from this promise as a single array to use.
        resolve([empInfo?.name, yearsEmployed, newVacationBalance]);
    });
}

async function asyncSendEmail(emailApi: EmailApi, payrollInfo: Payroll, addresses: AddressBook[], employees: Employee[]) {
    //Moran's note: adding a timer to see the performance.
    const startTime = Date.now();
    let addressInfo = addresses.find(x => x.emp_id == payrollInfo.emp_id);
    await Promise.all(employees.map(empInfo => {
        if (empInfo.id == payrollInfo.emp_id) {
            calculateVacation(payrollInfo, empInfo)
                .then(([empInfoName, yearsEmployed, newVacationBalance]) => {
                    if (addressInfo != undefined) {
                        emailApi.sendEmail(
                            addressInfo.email,
                            "Good news!",
                            `Dear ${empInfoName}\n` +
                            `based on your ${yearsEmployed} years of employment, you have been granted ${yearsEmployed} days of vacation, bringing your total to ${newVacationBalance}`
                        );
                    }
                });
        }
    }));
    const msElapsed = Date.now() - startTime;
    console.log(`Async function took ${msElapsed} ms to complete.`);
}

function grantVacation(
    emailApi: EmailApi,
    payroll: Payroll[],
    addresses: AddressBook[],
    employees: Employee[]) {

    for (let i = 0; i < payroll.length; i++) {
        let payrollInfo = payroll[i];
        asyncSendEmail(emailApi, payrollInfo, addresses, employees);
    }
}

// for the testing part I'll implement sendEmail as printing:
class myEmailApi implements EmailApi {
    sendEmail(email: string, subject: string, body: string): void {
        console.log('********************');
        console.log(`To ${email}, Subject: ${subject}, body: ${body}`);
        console.log('********************');
    }
}

let myPayroll: Payroll[] = [
    { emp_id: "1", vacationDays: 1 },
    { emp_id: "2", vacationDays: 2 },
    { emp_id: "3", vacationDays: 3 },
    { emp_id: "4", vacationDays: 4 },
    { emp_id: "5", vacationDays: 5 },
    { emp_id: "6", vacationDays: 6 }
];

let myAdress: AddressBook[] = [
    { emp_id: "1", first: "emp", last: "number 1", email: "emp1@gmail.com" },
    { emp_id: "2", first: "emp", last: "number 2", email: "emp2@gmail.com" },
    { emp_id: "3", first: "emp", last: "number 3", email: "emp3@gmail.com" },
    { emp_id: "4", first: "emp", last: "number 4", email: "emp4@gmail.com" },
    { emp_id: "5", first: "emp", last: "number 5", email: "emp5@gmail.com" },
    { emp_id: "6", first: "emp", last: "number 6", email: "emp6@gmail.com" },
];

let myEmployees: Employee[] = [
    { id: "1", name: "emp number 1", startDate: new Date("2020-01-01"), endDate: new Date("2025-01-01") },
    { id: "2", name: "emp number 2", startDate: new Date("2019-01-01"), endDate: new Date("2025-01-01") },
    { id: "3", name: "emp number 3", startDate: new Date("2018-01-01"), endDate: new Date("2025-01-01") },
    { id: "4", name: "emp number 4", startDate: new Date("2017-01-01"), endDate: new Date("2025-01-01") },
    { id: "5", name: "emp number 5", startDate: new Date("2016-01-01"), endDate: new Date("2025-01-01") },
    { id: "6", name: "emp number 6", startDate: new Date("2015-01-01"), endDate: new Date("2025-01-01") },
];

grantVacation(new myEmailApi(), myPayroll, myAdress, myEmployees);

导出接口地址簿{
emp_id:string | null;
第一:字符串;
最后:字符串;
电子邮件:字符串;
}
出口接口工资单{
emp_id:string;
假期天数:天数;
}
接口员工{
id:字符串;
名称:字符串;
起始日期:日期;
endDate:日期|空;
}
导出接口EmailApi{
sendmail(email:string,subject:string,body:string):void;
}
功能年份(开始日期:日期,结束日期:日期):编号{
常数毫秒每秒=365*24*60*60*1000;
返回Math.trunc((endDate.getTime()-startDate.getTime())/millissecondsperyear);
}
/**
*我们已经决定给每位员工发放奖金假期,每年工作一天
*我们需要给他们发邮件通知。
*/
功能计算评估(payrollInfo:Payroll,empInfo:Employee):承诺{
//将同步函数“包装”在承诺中并完成计算。
返回新承诺((解决)=>{
让今天=新日期();
设yearsEmployed=0;
如果(empInfo!=未定义){
yearsEmployed=yearsSince(empInfo.startDate,今天);
}
让newVacationBalance=yearsEmployed+payrollInfo.vacationDays;
//将此承诺中的所有相关值作为单个数组返回以供使用。
解析([empInfo?.name,部署年份,newVacationBalance]);
});
}
异步函数asyncSendEmail(emailApi:emailApi,payrollInfo:Payroll,地址:通讯簿[],员工:员工[]){
//莫兰注:添加计时器以查看性能。
const startTime=Date.now();
让addressInfo=addresses.find(x=>x.emp\u id==payrollInfo.emp\u id);
等待承诺.all(employees.map)(empInfo=>{
如果(empInfo.id==payrollInfo.emp_id){
计算评估(工资汇总信息、empInfo)
.然后(([empInfoName,yearsEmployed,newVacationBalance])=>{
如果(地址信息!=未定义){
emailApi.sendmail(
addressInfo.email,
“好消息!”,
`亲爱的${empInfoName}\n`+
`根据您${yearsememployed}年的工作年限,您已获得${yearsEmployed}天的假期,使您的总假期达到${newVacationBalance}`
);
}
});
}
}));
const msepersed=Date.now()-startTime;
log(`Async函数需要${msepersed}毫秒才能完成。`);
}
功能颗粒(
emailApi:emailApi,
工资总额:工资总额[],
地址:通讯簿[],
员工:员工[]){
for(设i=0;i
我真的很想知道我做错了什么?也许我的异步实现方式遗漏了一些基本知识? 也许代码是可以的,但是当测量给定测试数据的时间(我可以使其大于6)时,是不是太小了

提前谢谢

  • 你可以用你的
  • 查看代码时,最慢的部分似乎是2个“find”
  • 你需要更多的条目才能注意到实际的改进
  • 如果你想要的是速度,