前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【JavaScript ——异步函数】封装 Promisefy 函数(蓝桥杯真题-2425)【合集】

【JavaScript ——异步函数】封装 Promisefy 函数(蓝桥杯真题-2425)【合集】

作者头像
Rossy Yan
发布2025-02-13 09:15:48
发布2025-02-13 09:15:48
4700
代码可运行
举报
运行总次数:0
代码可运行

背景介绍

我们知道在浏览器中 JavaScript 是单线程运行的,而回调函数曾经是 JavaScript 中实现异步函数的主要方式,面对这样的嵌套回调,处理错误也会变得非常困难:你必须在“金字塔”的每一级处理错误,而不是在最高一级一次完成错误处理,所以大多数现代异步 API 采用的都是 Promise 的形式。 下面就请你以 Node.js 中常用的读取文件操作为例,封装一个 Promisefy 函数,将回调形式调用的读取文件方法转换成一个 Promise 的版本。


准备步骤

目录结构如下:

代码语言:javascript
代码运行次数:0
复制
├── index.js
└── test.md 

其中:

  • index.js 是需要补充代码的 js 文件。
  • test.md 供读取的示例文件。

注意:打开环境后发现缺少项目代码,请复制下述命令至命令行进行下载。

代码语言:javascript
代码运行次数:0
复制
cd /home/project
wget https://labfile.oss.aliyuncs.com/courses/18164/dist_01.zip
unzip dist_01.zip
mv dist/* ./
rm -rf dist*

目标效果

请在 index.js 文件中的补全代码,完成 promisefy 函数的封装。将 fs 中的 readFile 方法 promise 化。也就是说 readFileSync 方法执行后,会返回一个 promise,可以调用 then 方法执行成功的回调或失败的回调。

在实际应用中,一个函数满足这几个条件,就可以被 promisify 化:

  • 该方法必须包含回调函数
  • 回调函数必须执行
  • 回到函数第一个参数代表 err 信息,第二个参数代表成功返回的结果

在控制台运行:

代码语言:javascript
代码运行次数:0
复制
node index

此时应打印出 true,即:回调形式的 fs.readFile 方法读取同个文件的结果与 Promise 形式读取结果一致。


要求规定

  • 请按照给出的步骤操作,切勿修改默认提供的文件名称、文件夹路径等。

判分标准

  • 本题完全实现题目目标得满分,否则得 0 分。

通关代码✔️

代码语言:javascript
代码运行次数:0
复制
const fs = require('fs');
const path = require('path');
const textPath = path.join(__dirname, '/test.md');

// 读取示例文件
fs.readFile(textPath, 'utf8', (err, contrast) => {
    // 通过 promisify 转化为链式调用
    const readFileSync = promisify(fs.readFile);

    readFileSync(textPath, 'utf8')
      .then((res) => {
            console.log(res === contrast); // 此处结果预期:true,即 promise 返回内容与前面读取内容一致
        })
      .catch((err) => {
            console.error(err);
        });
});

const promisify = (fn) => {
    return function (...args) {
        return new Promise((resolve, reject) => {
            // 将回调函数作为最后一个参数传入原函数
            fn(...args, (err, result) => {
                if (err) {
                    // 如果发生错误,拒绝 Promise
                    reject(err);
                } else {
                    // 如果没有错误,解决 Promise 并返回结果
                    resolve(result);
                }
            });
        });
    };
};

module.exports = promisify; // 请勿删除该行代码

代码解析📑

整体功能概述

这段 Node.js 代码的主要目的是演示如何将一个遵循错误优先回调风格的函数(如 fs.readFile)转换为返回 Promise 的函数,以便使用 Promise 的链式调用特性。具体步骤是先使用传统的回调方式读取文件内容,然后将 fs.readFile 封装成返回 Promise 的函数再次读取同一文件,最后比较两次读取的内容是否一致。

代码详细讲解

1. 引入模块

代码语言:javascript
代码运行次数:0
复制
const fs = require('fs');
const path = require('path');
  • fs 模块是 Node.js 内置的文件系统模块,用于对文件进行读写等操作。
  • path 模块是 Node.js 内置的路径处理模块,用于处理和转换文件路径。

2. 构建文件路径

代码语言:javascript
代码运行次数:0
复制
const textPath = path.join(__dirname, '/test.md');
  • __dirname 是 Node.js 中的一个全局变量,表示当前执行脚本所在的目录。
  • path.join() 方法用于将多个路径片段拼接成一个完整的路径,这里将当前目录和 test.md 文件拼接在一起,得到文件的完整路径。

3. 使用传统回调方式读取文件

代码语言:javascript
代码运行次数:0
复制
fs.readFile(textPath, 'utf8', (err, contrast) => {
    // 通过 promisify 转化为链式调用
    const readFileSync = promisify(fs.readFile);

    readFileSync(textPath, 'utf8')
      .then((res) => {
            console.log(res === contrast); // 此处结果预期:true,即 promise 返回内容与前面读取内容一致
        })
      .catch((err) => {
            console.error(err);
        });
});
  • fs.readFile(textPath, 'utf8', callback):使用 fs 模块的 readFile 方法异步读取文件内容。
    • textPath 是要读取的文件的路径。
    • 'utf8' 表示以 UTF-8 编码格式读取文件,这样读取出来的内容是字符串类型。
    • callback 是一个回调函数,当文件读取完成后会调用该函数,它接受两个参数:
      • err:如果读取过程中发生错误,err 会包含错误信息;如果没有错误,errnull
      • contrast:读取到的文件内容。
  • 在回调函数内部,调用 promisify(fs.readFile)fs.readFile 转换为返回 Promise 的函数 readFileSync
  • 调用 readFileSync(textPath, 'utf8') 再次读取文件,返回一个 Promise 对象。
    • 使用 then 方法处理 Promise 成功的情况,将读取到的内容 res 与之前通过回调方式读取的内容 contrast 进行比较,并将结果打印到控制台。
    • 使用 catch 方法处理 Promise 失败的情况,将错误信息打印到控制台。

4. promisify 函数的实现

代码语言:javascript
代码运行次数:0
复制
const promisify = (fn) => {
    return function (...args) {
        return new Promise((resolve, reject) => {
            // 将回调函数作为最后一个参数传入原函数
            fn(...args, (err, result) => {
                if (err) {
                    // 如果发生错误,拒绝 Promise
                    reject(err);
                } else {
                    // 如果没有错误,解决 Promise 并返回结果
                    resolve(result);
                }
            });
        });
    };
};
  • promisify 函数接受一个遵循错误优先回调风格的函数 fn 作为参数。
  • 返回一个新的函数,该函数接受任意数量的参数 ...args(使用扩展运算符收集参数)。
  • 在返回的函数内部,创建一个新的 Promise 对象。
  • 调用原函数 fn,并将收集到的参数 ...args 传入,同时在最后添加一个回调函数。
    • 在回调函数中,如果 err 不为 null,表示发生了错误,调用 reject(err) 拒绝 Promise。
    • 如果 errnull,表示没有错误,调用 resolve(result) 解决 Promise 并返回结果。

5. 导出 promisify 函数

代码语言:javascript
代码运行次数:0
复制
module.exports = promisify; // 请勿删除该行代码

promisify 函数导出,以便在其他模块中可以使用。

工作流程▶️

  1. 引入模块:引入 fspath 模块,为后续的文件操作和路径处理做准备。
  2. 构建文件路径:使用 path.join 方法构建要读取的文件的完整路径。
  3. 传统回调方式读取文件:使用 fs.readFile 异步读取文件内容,当读取完成后,进入回调函数。
  4. 封装函数为 Promise:在回调函数内部,调用 promisify 函数将 fs.readFile 封装成返回 Promise 的函数 readFileSync
  5. 使用 Promise 再次读取文件:调用 readFileSync 再次读取文件,返回一个 Promise 对象。
  6. 处理 Promise 结果:使用 then 方法处理 Promise 成功的情况,比较两次读取的内容是否一致;使用 catch 方法处理 Promise 失败的情况,打印错误信息。
  7. 导出函数:将 promisify 函数导出,供其他模块使用。

测试结果👍

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-02-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景介绍
  • 准备步骤
  • 目标效果
  • 要求规定
  • 判分标准
  • 通关代码✔️
  • 代码解析📑
    • 整体功能概述
    • 代码详细讲解
  • 测试结果👍
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档