面试题答案
一键面试处理异步操作的几种方式
- 回调(Callback)
- 原理:将一个函数作为参数传递给另一个函数,当异步操作完成时,调用这个回调函数,并将结果作为参数传入。
- 缺点:容易导致回调地狱,即多层嵌套回调,代码可读性和维护性变差。
- Promise
- 原理:Promise 是一个代表异步操作最终完成(或失败)及其结果值的对象。它有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。一旦状态改变,就不会再变。
- 优点:通过链式调用.then() 方法来处理成功和失败,避免了回调地狱,使代码更具可读性。
- async/await
- 原理:async 函数是异步函数,它返回一个 Promise 对象。在 async 函数内部可以使用 await 关键字暂停函数执行,等待 Promise 解决(resolved),然后继续执行。
- 优点:语法上更接近同步代码,使异步操作看起来像同步操作,进一步提高了代码的可读性和可维护性。
在 TypeScript 环境下结合类型定义确保可靠性和可维护性
- Promise 的类型定义
- 在 TypeScript 中,Promise 有类型参数。例如,
Promise<T>
表示一个将解决为类型T
值的 Promise。如果一个函数返回一个 Promise,应明确其返回类型。
function asyncFunction(): Promise<string> { return new Promise((resolve, reject) => { setTimeout(() => { resolve('Hello, TypeScript'); }, 1000); }); }
- 在 TypeScript 中,Promise 有类型参数。例如,
- async/await 的类型定义
- async 函数的返回类型也是 Promise。当使用 await 时,TypeScript 会根据所等待的 Promise 的类型推断出结果的类型。
async function main() { const result = await asyncFunction(); // result 类型为 string console.log(result); }
实际应用场景的代码示例
假设我们有一个读取文件的异步操作,使用 fs
模块在 Node.js 中结合 TypeScript 和 async/await 实现。
import fs from 'fs';
import { promisify } from 'util';
const readFileAsync = promisify(fs.readFile);
async function readJsonFile<T>(path: string): Promise<T> {
try {
const data = await readFileAsync(path, 'utf8');
return JSON.parse(data);
} catch (error) {
throw new Error(`Error reading file: ${error.message}`);
}
}
// 使用示例
readJsonFile<{ message: string }>('example.json')
.then((jsonData) => {
console.log(jsonData.message);
})
.catch((error) => {
console.error(error.message);
});
在这个示例中,readFileAsync
使用 promisify
将 Node.js 的回调式 fs.readFile
转换为返回 Promise 的函数。readJsonFile
是一个泛型异步函数,它读取 JSON 文件并解析为指定类型 T
。通过明确的类型定义和 async/await 语法,代码既可靠又易于维护。