MST

星途 面试题库

面试题:Node.js 性能优化之高级难度 - 异步处理

Node.js 依赖异步I/O来实现高性能。假设你正在处理一个包含大量异步操作(如多个数据库查询、文件读取等)的复杂应用,如何利用Node.js的异步特性(如Promise、async/await)来优化性能,同时避免回调地狱?请结合具体代码示例说明如何进行优化设计,并且阐述如何处理异步操作中的错误。
37.6万 热度难度
前端开发Node.js

知识考点

AI 面试

面试题答案

一键面试

使用Promise优化性能并避免回调地狱

  1. Promise基础示例 假设我们有一个简单的异步函数模拟文件读取,使用fs模块的readFile方法,其原始回调形式如下:
const fs = require('fs');
fs.readFile('example.txt', 'utf8', (err, data) => {
    if (err) {
        console.error(err);
        return;
    }
    console.log(data);
});

使用Promise封装后:

const fs = require('fs');
const util = require('util');
const readFilePromise = util.promisify(fs.readFile);
readFilePromise('example.txt', 'utf8')
   .then(data => {
        console.log(data);
    })
   .catch(err => {
        console.error(err);
    });
  1. 多个异步操作优化 假设有多个数据库查询(这里简单模拟为异步函数)和文件读取操作。
// 模拟数据库查询
function dbQuery1() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Result of dbQuery1');
        }, 1000);
    });
}
function dbQuery2() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Result of dbQuery2');
        }, 1500);
    });
}
// 模拟文件读取
const fs = require('fs');
const util = require('util');
const readFilePromise = util.promisify(fs.readFile);

// 多个异步操作串行执行
dbQuery1()
   .then(result1 => {
        console.log(result1);
        return dbQuery2();
    })
   .then(result2 => {
        console.log(result2);
        return readFilePromise('example.txt', 'utf8');
    })
   .then(data => {
        console.log(data);
    })
   .catch(err => {
        console.error(err);
    });

// 多个异步操作并行执行
Promise.all([dbQuery1(), dbQuery2()])
   .then(results => {
        console.log(results[0]);
        console.log(results[1]);
        return readFilePromise('example.txt', 'utf8');
    })
   .then(data => {
        console.log(data);
    })
   .catch(err => {
        console.error(err);
    });

使用async/await优化性能并避免回调地狱

  1. async/await基础示例
const fs = require('fs');
const util = require('util');
const readFilePromise = util.promisify(fs.readFile);
async function readFileAsync() {
    try {
        const data = await readFilePromise('example.txt', 'utf8');
        console.log(data);
    } catch (err) {
        console.error(err);
    }
}
readFileAsync();
  1. 多个异步操作优化
// 模拟数据库查询
function dbQuery1() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Result of dbQuery1');
        }, 1000);
    });
}
function dbQuery2() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('Result of dbQuery2');
        }, 1500);
    });
}
// 模拟文件读取
const fs = require('fs');
const util = require('util');
const readFilePromise = util.promisify(fs.readFile);

async function performOperations() {
    try {
        // 串行执行
        const result1 = await dbQuery1();
        console.log(result1);
        const result2 = await dbQuery2();
        console.log(result2);
        const data = await readFilePromise('example.txt', 'utf8');
        console.log(data);

        // 并行执行
        const [result3, result4] = await Promise.all([dbQuery1(), dbQuery2()]);
        console.log(result3);
        console.log(result4);
        const data2 = await readFilePromise('example.txt', 'utf8');
        console.log(data2);
    } catch (err) {
        console.error(err);
    }
}
performOperations();

处理异步操作中的错误

  1. Promise方式:在Promise链中,每个.then方法后面都可以接一个.catch方法来捕获该链中前面Promise产生的错误。如果没有.catch,错误会一直向上冒泡到全局未捕获拒绝处理程序。
  2. async/await方式:在async函数中,使用try...catch块来捕获await操作产生的错误。如果没有try...catch,错误会抛出到函数外部,需要在调用该async函数的地方捕获处理。