ソースコードの読み取り:promifyify

ソースコードの読み取り:promifyify

導入

JavaScript では、コールバック関数は非同期操作を処理する一般的な方法です。ただし、コールバック関数を使用すると、コードのネストが深すぎて理解や保守が困難になる可能性があります。Promiseifyこの問題を解決することで、コールバックベースの非同期関数を返される関数に変換できるためPromise、開発者が非同期操作を処理したり、チェーン呼び出しを使用してコードを記述したりすることが容易になりPromise、非同期操作を処理するためのより明確で簡潔なコードが使用されます。

Promiseify使用方法は非常に簡単で、関数を呼び出して、変換する必要がある非同期関数をパラメータとして渡すだけです。Promiseify新しい関数を返します。この新しい関数はオブジェクトを返しますPromiseこの返された関数を呼び出すことで元の非同期操作を実行し、Promise連鎖呼び出しを使用して結果とエラーを処理できます。

promiseify基本的な使い方は以下の通りです。

  1. モジュールをインポートしますpromiseify(例として CommonJS)。
const promiseify = require('promiseify');
  1. 変換する必要がある関数をpromiseify関数に渡し、Promise関数の返されたバージョンを取得します。
const promiseFunc = promiseify(callbackFunc);
  1. promiseFunc非同期操作には返された関数を使用します。
promiseFunc(args)
  .then((result) => {
    
    
    // 处理成功的结果
  })
  .catch((error) => {
    
    
    // 处理错误
  });

promiseify動作原理は、元のコールバック関数を新しいコールバック関数でラップしPromisePromiseコールバック関数の実行結果に基づいて状態を決定することです。コールバック関数が正常に実行された場合、成功ステータスとしてPromise解析され、結果値が渡されます。コールバック関数が失敗した場合、コールバックPromise関数は拒否され、エラー オブジェクトが渡されます。

ソースコードの解釈

'use strict';

まず、コードは厳密モード ( 'use strict') を使用して、コードの厳密性とセキュリティを確保します。

次に、2 つのパラメータ、および(オプション)promiseifyを受け入れる関数が定義されますパラメータは変換する必要がある関数であり、パラメータは関数として機能するコンテキスト ( ) ですmethodctxmethodctxthis

/**
 * promiseify
 * @param {function} method function
 * @param {object} ctx optional ctx for method
 */
function promiseify(method, ctx) {
    
    

  // check first
  if (typeof method !== 'function') {
    
    
    throw new TypeError(String(method) + ' is not a function');
  }

  return function() {
    
    

    // runtime args
    var args = [].slice.call(arguments);

    // runtime this
    ctx = ctx || this;

    return new Promise(function(resolve, reject) {
    
    

      args.push(function(err) {
    
    
        if (err) {
    
    
          return reject(err);
        }
        var arg = [].slice.call(arguments);
        if (arg.length === 2) {
    
    
          resolve.call(this, arg[1]);
        } else {
    
    
          resolve.call(this, arg.slice(1));
        }
      });

      try {
    
    
        method.apply(ctx, args);
      } catch (err) {
    
    
        reject(err);
      }
    });
  };
}
  1. コードでは、最初にパラメータ チェックを実行して、メソッド パラメータが関数であるかどうかを確認します。関数でない場合は、型エラーがスローされます。
  2. 次に、新しい関数が返され、それがPromise関数の返されたバージョンになります。
  3. 新しい関数内では、まず実行時パラメータ ( arguments) を取得し、それらを配列に変換します。
  4. 次に、渡されたコンテキスト パラメーターまたはデフォルトのコンテキスト ( ) に基づいてthis関数の実行コンテキストを設定します。
  5. 次に、新しいコールバック関数を作成しPromisePromiseコンストラクターのパラメーターとして新しいコールバック関数を渡します。このコールバック関数は、resolveと の2 つのパラメータを受け入れますreject
  6. コールバック関数では、まずエラーパラメータ( )の有無を確認しerr、エラーがあればrejectメソッドはPromise拒否され、エラーオブジェクトが渡されます。
  7. エラーがない場合は、[].slice.call(arguments)「コールバック関数のパラメーターを配列に変換する ( arg)」を使用します。
  8. resolve次に、呼び出し時に渡されるパラメータは、パラメータの長さに基づいて決定されます。パラメータの長さが の場合は2、エラー パラメータと結果パラメータがあることを意味します。このとき、resolveメソッドが呼び出され、結果パラメータ ( arg[1]) が渡されます。そうでない場合は、resolveメソッドが呼び出され、結果パラメータの配列 ( arg.slice(1)) が渡されます。合格した。
  9. 最後に、try-catch元の非同期関数 ( method.apply(ctx, args)) がブロック内で実行され、エラーが発生した場合、消費rejectメソッドはPromise拒否され、エラー オブジェクトが渡されます。
/**
 * promiseify all
 * @param  {object} o the target object
 * @return {object}   same to target object
 *
 * @example
 *   var fs = promiseify.all(require('fs'));
 *   fs.readFileAsync('file.txt', 'utf8')
 *     .then(function(s){ console.log(s); });
 *
 *   var Connection = require('mysql/lib/Connection');
 *   promiseify.all(Connection.prototype);
 *   // conn.connectAsync / conn.queryAsync / conn.endAsync available now
 */
promiseify.all = function(o) {
    
    
  Object.keys(o)
    .filter(function(m) {
    
    
      return typeof o[m] === 'function';
    })
    .forEach(function(m) {
    
    
      o[m + 'Async'] = promiseify(o[m]);
    });
  return o;
};

この部分は、promiseify.allオブジェクトをパラメータとして受け取り、そのオブジェクトのすべてのプロパティを反復処理する関数です。値が関数である属性の場合、それをPromise関数のバージョンに変換し、元の関数名とAsync接尾辞を付けて新しい関数をオブジェクトに追加します。

Object.defineProperty(promiseify, "__esModule", {
    
     value: true });
promiseify.default = promiseify;
module.exports = promiseify;

このコードは主に、promiseify関数をモジュールとしてエクスポートするために使用されます。まず、Object.definePropertyメソッドを使用して、という名前の値を持つプロパティをオブジェクトにpromiseify追加しますこれは、モジュールが ES モジュールであることを示します。次に、プロパティを関数自体に設定します。このように、構文インポートを使用すると、関数を直接取得できます。最後に、関数をモジュールとしてエクスポートします。このようにして、 import 構文を使用すると関数を取得できます"__esModule"truepromiseify.defaultpromiseifyimportpromiseifymodule.exportspromiseifyrequirepromiseify

拡大する

JavaScript では、配列のようなオブジェクトとは、配列の特性を持つが、真の配列ではないオブジェクトを指します。これらには、配列のような長さプロパティと、インデックスによって要素にアクセスする機能があります。ただし、配列のようなオブジェクトには、配列のプロトタイプ メソッドとプロパティがありません。

一般的な配列のようなオブジェクトには次のものがあります。

  1. argumentsオブジェクト: 関数に渡されるパラメータを保存するために関数内で自動的に作成されるオブジェクト。
  2. DOM 要素リスト (NodeList): DOM 要素のクエリによって返されるオブジェクトのコレクション (querySelectorAllメソッドを通じて取得された結果など)。
  3. 文字列: 文字列内の文字にはインデックスによってアクセスできます。
  4. 配列のようなオブジェクト: 一部のオブジェクトは、たとえば配列のような反復子インターフェイスを実装することによって、配列に似るように設計される場合があります。

配列のようなオブジェクトを実際の配列に変換するには、いくつかの方法があります。

  1. 使用法Array.from():Array.from()このメソッドは、配列のようなオブジェクトまたは反復可能なオブジェクトを新しい配列に変換できます。例えば:var array = Array.from(arrayLike);
  2. スプレッド演算子を使用する (スプレッド演算子): スプレッド演算子 (...) は、配列のようなオブジェクトを新しい配列にスプレッドできます。例えば:var array = [...arrayLike];
  3. 使用法: メソッドArray.prototype.slice.call()を呼び出しArray.prototype.slice、配列のようなオブジェクトをコンテキストとして渡すことにより、配列のようなオブジェクトを配列に変換できます。例えば:var array = Array.prototype.slice.call(arrayLike);
  4. 使用法:メソッドを呼び出し、配列のようなオブジェクトをパラメーターとして渡すことによって、配列のようなオブジェクトを配列Array.prototype.concat()に変換できます。Array.prototype.concat例えば:var array = Array.prototype.concat.call([], arrayLike);

上記のメソッドはすべて、元の配列のようなオブジェクトを直接変更するのではなく、新しい配列を作成することに注意してください。

おすすめ

転載: blog.csdn.net/p1967914901/article/details/132024074