>  기사  >  웹 프론트엔드  >  Node의 util.promisify() 함수에 대한 심층 분석

Node의 util.promisify() 함수에 대한 심층 분석

青灯夜游
青灯夜游앞으로
2023-04-12 17:56:151386검색

Node.js의 내장 유틸리티 패키지에는 콜백 기반 함수를 Promise 기반 함수로 변환할 수 있는 promisify() 함수가 있습니다. 이 글에서는 Node.js의 util.promisify() 함수를 소개하겠습니다. 도움이 되길 바랍니다.

Node의 util.promisify() 함수에 대한 심층 분석

콜백 기반 API와 함께 Promise chainingasync/await을 사용할 수 있습니다.

예를 들어 Node.js의 fs 패키지는 콜백을 사용합니다. 일반적으로 파일을 읽으려면 콜백을 사용해야 합니다.

const fs = require('fs');
fs.readFile('./package.json', function callback(err, buf) {
    const obj = JSON.parse(buf.toString('utf8'));
    obj.name; // 'masteringjs.io'
});

util.promisify()를 사용하여 fs.readFile() 함수를 약속하다. [권장 관련 튜토리얼: nodejs 동영상 튜토리얼util.promisify()fs.readFile() 函数转换为返回 Promise 的函数。【相关教程推荐:nodejs视频教程编程教学

const fs = require('fs');
const util = require('util');

// 将 `fs.readFile()` 转换为一个函数,该函数接受相同的参数但返回一个 Promise
const readFile = util.promisify(fs.readFile);

// 现在可以对 `readFile()` 使用 `await` 了!
const buf = await readFile('./package.json');

const obj = JSON.parse(buf.toString('utf8'));
obj.name; // 'masteringjs.io'

简单实现

util.promisify() 在内部是如何工作的?npm 上有一个 polyfill,你可以 在这里阅读完整的实现。你也可以 在这里找到 Node.js 的实现,不过出于教育目的,polyfill 更容易阅读。

util.promisify() 的核心思想是 在你传递的参数基础上添加了一个回调函数。这个回调函数解析(resolve)或拒绝(rejected) promisified 函数返回的 Promise。

有点啰嗦了,以下是 util.promisify() 方法一个简化的实现版本。

const fs = require('fs');

// `util.promisify()` 的简化实现。不涵盖所有情况,不要在生产环境中使用!
function promisify(fn) {
    return function () {
        const args = Array.prototype.slice.call(arguments);
        return new Promise((resolve, reject) => {
            fn.apply(this, [].concat(args).concat([(err, res) => {
                if (err) {
                    return reject(err);
                }
                resolve(res);
            }]));
        });
    }
}

// 将 `fs.readFile()` 转换为一个函数,该函数接受相同的参数但返回一个 Promise
const readFile = util.promisify(fs.readFile);

// 现在可以对 `readFile()` 使用 `await` 了!
const buf = await readFile('./package.json');

const obj = JSON.parse(buf.toString('utf8'));
obj.name; // 'masteringjs.io'

怎么理解?首先,util.promisify() 会向你传递的参数添加 1 个额外参数,然后使用这些新参数调用原始函数。那么底层函数就要支持这些数量的参数调用,举例:如果你正在使用类型为 [String,Object] 的 2 个参数调用 promisified 函数 myFn(),请确保原始函数支持调用签名 [String, Object, Function]

其次,util.promisify() 对于 函数上下文 有影响。

丢失上下文

丢失上下文(Losing Context) 表示调用函数时内部 this 值不正确 。丢失上下文是转换后的函数的常见问题:

class MyClass {
  myCallbackFn(cb) {
    cb(null, this);
  }
}

const obj = new MyClass();
const promisified = require('util').promisify(obj.myCallbackFn);

const context = await promisified();
context; // 打印 `undefined` 而非 `MyClass` 实例!

this, 프로그래밍 교육]

class MyClass {
  myCallbackFn(cb) {
    cb(null, this);
  }
}

const obj = new MyClass();
// 保留上下文,因为 `promisified` 是 `obj` 的一个属性
obj.promisified = require('util').promisify(obj.myCallbackFn);

const context = await obj.promisified();
context === obj; // true

간단한 구현

util. promisify()는 내부적으로 어떻게 작동하나요? npm에는 폴리필이 있습니다. 여기에서 전체 구현을 읽어보세요 . 여기에서 Node.js 구현을 찾으세요

. 하지만 교육 목적으로는 폴리필이 더 읽기 쉽습니다. 🎜🎜util.promisify() 핵심 아이디어는 전달한 매개변수에 따라 콜백 함수 🎜를 추가합니다. 이 콜백 함수는 약속된 함수에서 반환된 약속을 확인하거나 거부합니다. 🎜🎜좀 장황합니다. 다음은 util.promisify() 메서드의 단순화된 구현 버전입니다. 🎜rrreee🎜어떻게 이해하셨나요? 먼저 util.promisify()는 전달하는 매개변수에 1개의 추가 매개변수를 추가한 다음 이러한 새 매개변수를 사용하여 원래 함수를 호출합니다. 그런 다음 기본 함수는 다음과 같은 수의 매개변수 호출을 지원해야 합니다. 예를 들어 [String, Object] 유형의 매개변수 2개를 사용하여 약속된 함수 myFn()을 호출하는 경우 원래 함수가 [String, Object, Function] 호출 서명을 지원하는지 확인하세요. 🎜🎜두 번째로, 함수 컨텍스트 🎜가 영향을 미칩니다. 🎜

컨텍스트 손실

🎜
컨텍스트 손실(Losing Context) 🎜 함수 호출 시 내부 this 값이 올바르지 않음을 나타냅니다. 컨텍스트 손실은 변환된 함수에서 흔히 발생하는 문제입니다. 🎜rrreee🎜this는 함수가 호출될 때 해당 객체가 속한 객체 🎜를 나타냅니다. 따라서 약속된 함수를 동일한 객체의 속성으로 설정하여 컨텍스트를 보존할 수 있습니다: 🎜rrreee🎜더 많은 노드 관련 지식을 보려면 🎜nodejs tutorial🎜을 방문하세요! 🎜

위 내용은 Node의 util.promisify() 함수에 대한 심층 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 juejin.cn에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제