ソースコードの読み取り:promifyify
ソースコードの読み取り:promifyify
導入
JavaScript では、コールバック関数は非同期操作を処理する一般的な方法です。ただし、コールバック関数を使用すると、コードのネストが深すぎて理解や保守が困難になる可能性があります。Promiseify
この問題を解決することで、コールバックベースの非同期関数を返される関数に変換できるためPromise
、開発者が非同期操作を処理したり、チェーン呼び出しを使用してコードを記述したりすることが容易になりPromise
、非同期操作を処理するためのより明確で簡潔なコードが使用されます。
Promiseify
使用方法は非常に簡単で、関数を呼び出して、変換する必要がある非同期関数をパラメータとして渡すだけです。Promiseify
新しい関数を返します。この新しい関数はオブジェクトを返しますPromise
。この返された関数を呼び出すことで元の非同期操作を実行し、Promise
連鎖呼び出しを使用して結果とエラーを処理できます。
promiseify
基本的な使い方は以下の通りです。
- モジュールをインポートします
promiseify
(例として CommonJS)。
const promiseify = require('promiseify');
- 変換する必要がある関数を
promiseify
関数に渡し、Promise
関数の返されたバージョンを取得します。
const promiseFunc = promiseify(callbackFunc);
promiseFunc
非同期操作には返された関数を使用します。
promiseFunc(args)
.then((result) => {
// 处理成功的结果
})
.catch((error) => {
// 处理错误
});
promiseify
動作原理は、元のコールバック関数を新しいコールバック関数でラップしPromise
、Promise
コールバック関数の実行結果に基づいて状態を決定することです。コールバック関数が正常に実行された場合、成功ステータスとしてPromise
解析され、結果値が渡されます。コールバック関数が失敗した場合、コールバックPromise
関数は拒否され、エラー オブジェクトが渡されます。
ソースコードの解釈
'use strict';
まず、コードは厳密モード ( 'use strict'
) を使用して、コードの厳密性とセキュリティを確保します。
次に、2 つのパラメータ、および(オプション)promiseify
を受け入れる関数が定義されます。パラメータは変換する必要がある関数であり、パラメータは関数として機能するコンテキスト ( ) です。method
ctx
method
ctx
this
/**
* 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);
}
});
};
}
- コードでは、最初にパラメータ チェックを実行して、メソッド パラメータが関数であるかどうかを確認します。関数でない場合は、型エラーがスローされます。
- 次に、新しい関数が返され、それが
Promise
関数の返されたバージョンになります。 - 新しい関数内では、まず実行時パラメータ (
arguments
) を取得し、それらを配列に変換します。 - 次に、渡されたコンテキスト パラメーターまたはデフォルトのコンテキスト ( ) に基づいて
this
関数の実行コンテキストを設定します。 - 次に、新しいコールバック関数を作成し
Promise
、Promise
コンストラクターのパラメーターとして新しいコールバック関数を渡します。このコールバック関数は、resolve
と の2 つのパラメータを受け入れますreject
。 - コールバック関数では、まずエラーパラメータ( )の有無を確認し
err
、エラーがあればreject
メソッドはPromise
拒否され、エラーオブジェクトが渡されます。 - エラーがない場合は、
[].slice.call(arguments)
「コールバック関数のパラメーターを配列に変換する (arg
)」を使用します。 resolve
次に、呼び出し時に渡されるパラメータは、パラメータの長さに基づいて決定されます。パラメータの長さが の場合は2
、エラー パラメータと結果パラメータがあることを意味します。このとき、resolve
メソッドが呼び出され、結果パラメータ (arg[1]
) が渡されます。そうでない場合は、resolve
メソッドが呼び出され、結果パラメータの配列 (arg.slice(1)
) が渡されます。合格した。- 最後に、
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"
true
promiseify.default
promiseify
import
promiseify
module.exports
promiseify
require
promiseify
拡大する
JavaScript では、配列のようなオブジェクトとは、配列の特性を持つが、真の配列ではないオブジェクトを指します。これらには、配列のような長さプロパティと、インデックスによって要素にアクセスする機能があります。ただし、配列のようなオブジェクトには、配列のプロトタイプ メソッドとプロパティがありません。
一般的な配列のようなオブジェクトには次のものがあります。
arguments
オブジェクト: 関数に渡されるパラメータを保存するために関数内で自動的に作成されるオブジェクト。- DOM 要素リスト (NodeList): DOM 要素のクエリによって返されるオブジェクトのコレクション (
querySelectorAll
メソッドを通じて取得された結果など)。 - 文字列: 文字列内の文字にはインデックスによってアクセスできます。
- 配列のようなオブジェクト: 一部のオブジェクトは、たとえば配列のような反復子インターフェイスを実装することによって、配列に似るように設計される場合があります。
配列のようなオブジェクトを実際の配列に変換するには、いくつかの方法があります。
- 使用法
Array.from()
:Array.from()
このメソッドは、配列のようなオブジェクトまたは反復可能なオブジェクトを新しい配列に変換できます。例えば:var array = Array.from(arrayLike);
- スプレッド演算子を使用する (スプレッド演算子): スプレッド演算子 (...) は、配列のようなオブジェクトを新しい配列にスプレッドできます。例えば:
var array = [...arrayLike];
- 使用法: メソッド
Array.prototype.slice.call()
を呼び出しArray.prototype.slice
、配列のようなオブジェクトをコンテキストとして渡すことにより、配列のようなオブジェクトを配列に変換できます。例えば:var array = Array.prototype.slice.call(arrayLike);
- 使用法:メソッドを呼び出し、配列のようなオブジェクトをパラメーターとして渡すことによって、配列のようなオブジェクトを配列
Array.prototype.concat()
に変換できます。Array.prototype.concat
例えば:var array = Array.prototype.concat.call([], arrayLike);
上記のメソッドはすべて、元の配列のようなオブジェクトを直接変更するのではなく、新しい配列を作成することに注意してください。