Heim  >  Artikel  >  Web-Frontend  >  Ein detaillierter Blick auf die promisify()-Methode des Node.js-Util-Moduls

Ein detaillierter Blick auf die promisify()-Methode des Node.js-Util-Moduls

青灯夜游
青灯夜游nach vorne
2021-08-27 10:33:233205Durchsuche

Ein detaillierter Blick auf die promisify()-Methode des Node.js-Util-Moduls

Node.js Das integrierte util-Modul verfügt über ein promisify() Methodeutil 模块有一个 promisify() 方法,该方法将基于回调的函数转换为基于 Promise 的函数。这使您可以将 Promise 链和 async/await 与基于回调的 API 结合使用。

例如,Node.js 的 fs 模块在读取文件时,需要使用回调:

const fs = require('fs')

fs.readFile('./package.json', function callback(err, buf) {
  const obj = JSON.parse(buf.toString('utf8'))
  console.log(obj.name) // 'Example' -> package.json 包名
})

我们可以使用 util.promisify()fs.readFile() 的回调函数转换为返回 Promise 函数:

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'))
console.log(obj.name) // 'Example'

promisify 是如何工作的?

util.promisify() 在后台是如何工作的?npm 上有一个 polyfill,您可以在这里阅读完整的实现。您也可以在这里找到 Node.js 的实现,不过为了便于理解,polyfill 更易于阅读。【推荐学习:《nodejs 教程》】

util.promisify() 背后的关键思想是向传入的参数添加回调函数。该回调函数解析或拒绝 promisified 函数返回的 Promise。

为了便于理解,下面是一个非常简化的 util.promisify() 自定义实现示例:

const fs = require('fs')

// util.promisify() 的简化实现。不包括所有情况,不要在 prod 环境中使用此选项!
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 != null) {
          return reject(err)
        }
        resolve(res)
      }]))
    })
  }
}

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

// 现在可以将 readFile() 与 await 一起使用!
const buf = await readFile('./package.json')

const obj = JSON.parse(buf.toString('utf8'))
console.log(obj.name) // 'Example'

那么这是什么意思呢?首先,util.promisify()向传入的参数添加 1 个额外参数,然后使用这些新参数调用原始函数。这意味着底层函数需要支持该数量的参数。因此,如果您要调用myFn()具有 2 个类型参数的promisified 函数 [String, Object],请确保原始函数支持[String, Object, Function]

那么这意味着什么呢?首先,util.promisify() 向传入的参数添加一个额外参数,然后使用这些新参数调用原始函数。这意味着基础函数需要支持该数量的参数。因此,如果您使用 [String, Object] 类型的 2 个参数调用 promisified 函数 myFn(),请确保原始函数支持 [String, Object, Function]

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

丢失上下文

丢失上下文(this)意味着函数调用以错误的值结束。丢失上下文是转换函数的常见问题:

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

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

const context = await promisified()
console.log(context) // 打印 undefined 而不是 MyClass 实例!

请记住,this, die Callback-basierte Funktionen in Promise-basierte Funktionen konvertiert. Dadurch können Sie Promise-Ketten und async/await mit Callback-basierten APIs verwenden.

Zum Beispiel muss das fs-Modul von Node.js beim Lesen einer Datei einen Rückruf verwenden:

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()
console.log(context === obj) // true
Wir können util.promisify() verwenden, um fs Die Rückruffunktion von .readFile() wird in eine Promise-zurückgebende Funktion umgewandelt:

rrreee

Wie funktioniert promisify?

🎜util.promisify() Wie funktioniert es hinter den Kulissen? Es gibt einen Polyfill🎜 auf npm, den Sie hier lesen können Vollständige Implementierung 🎜. Sie finden es auch hier nodejs Tutorial🎜"]🎜🎜 Die Schlüsselidee hinter util.promisify() ist Fügt den übergebenen Parametern eine Callback-Funktion hinzu 🎜. Diese Rückruffunktion löst das von der versprochenen Funktion zurückgegebene Promise auf oder lehnt es ab. 🎜🎜Zum besseren Verständnis finden Sie hier ein sehr vereinfachtes benutzerdefiniertes Implementierungsbeispiel von util.promisify(): 🎜rrreee🎜Was bedeutet das also? Zuerst fügt util.promisify() einen zusätzlichen Parameter zu den übergebenen Parametern hinzu und ruft dann die ursprüngliche Funktion mit diesen neuen Parametern auf. Das bedeutet, dass die zugrunde liegende Funktion diese Anzahl von Argumenten unterstützen muss. Wenn Sie also myFn() eine versprochene Funktion [String, Object] mit zwei Typparametern aufrufen, stellen Sie sicher, dass die ursprüngliche Funktion [String, Object, Function] unterstützt ]. 🎜🎜Was bedeutet das also? Zuerst fügt util.promisify() einen zusätzlichen Parameter zu den übergebenen Parametern hinzu und ruft dann die ursprüngliche Funktion mit diesen neuen Parametern auf. Das bedeutet, dass die zugrunde liegende Funktion diese Anzahl von Argumenten unterstützen muss. Wenn Sie daher die versprochene Funktion myFn() mit zwei Argumenten vom Typ [String, Object] aufrufen, stellen Sie sicher, dass die ursprüngliche Funktion [String, Object] unterstützt , Funktion ]. 🎜🎜Zweitens hat util.promisify() einen Einfluss auf den Funktionskontext (this). 🎜

Verlorener Kontext

🎜Verlorener Kontext (this) bedeutet, dass der Funktionsaufruf mit dem falschen Wert endet. Der Verlust des Kontexts ist ein häufiges Problem bei Umwandlungsfunktionen: 🎜rrreee🎜 Denken Sie daran, dass this jedes Objekt ist, das Eigenschaften enthält, wenn die Funktion aufgerufen wird. So können Sie den Kontext bewahren, indem Sie die versprochene Funktion auf eine Eigenschaft desselben Objekts setzen: 🎜rrreee🎜Weitere Programmierkenntnisse finden Sie unter: 🎜Programmiervideos🎜! ! 🎜

Das obige ist der detaillierte Inhalt vonEin detaillierter Blick auf die promisify()-Methode des Node.js-Util-Moduls. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:juejin.cn. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen