4

十分に文書化されたq フレームワークであっても、Node.js で数日間プログラミングしていると、理解するのは非常に困難です。しかし、私はそれについて学ぶのが好きです!

var Q  = require('q');
var fs = require('fs');

// Make the promise manually (returns a value or throws an error)
var read1 = fs.readFile(fname, enc, function (err, data) {
    if(err) throw err;

    return data;
});

// Convenient helper for node, equivalent to read1?
var read2 = Q.nfbind(fs.readFile);

// Uh?!
var read3 = function (fname, enc) {
    var deferred = Q.defer();

    fs.readFile(fname, enc, function (error, text) {
        if (error) {
            deferred.reject(new Error(error));
        } else {
            deferred.resolve(text);
        }

        return deferred.promise;
    });
};


// Execute
Q.fncall(read1).then(function (data) {}, function (err) {}).done();

read1read2およびread3同等ですか?Q.nfbind関数の最後のパラメーターが次のスタイルのコールバックを受け入れるたびに使用できますfunction (err, value)か?

4

1 に答える 1

11

あなたの例にはいくつかのエラーがあります。

読み取り1

これは「手動で約束をする」ことではなく、通常の非同期呼び出しを行っているだけです。あなたのコードでは、readFileすぐに呼び出すのでread1、戻り値は になりreadFileますundefined。に似た動作を得るには、次のようにする必要がread2ありread3ます。

var read1 = function(fname, env, success, error){
  fs.readFile(fname, enc, function (err, data) {
    // Throwing here would just crash your application.
    if(err) error(err);

    // Returning from inside 'readFile' does nothing, instead you use a callback.
    else success(data);
  });
};

read2

// Not equivalent to read1 because of the notes above,
// Equivalent to read3, with the fixes I mention below.
var read2 = Q.nfbind(fs.readFile);

read3

var read3 = function (fname, enc) {
    var deferred = Q.defer();

    fs.readFile(fname, enc, function (error, text) {
        if (error) {
            // 'error' is already an error object, you don't need 'new Error()'.
            deferred.reject(error);
        } else {
            deferred.resolve(text);
        }

        // HERE: Again returning a value from 'readFile' does not make sense.
        return deferred.promise;
    });

    // INSTEAD: Return here, so you can access the promise when you call 'read3'.
    return deferred.promise.
};

実際nfbind、コールバックを最後のパラメーターとして取るものなら何でも使用できます。私のコメントで、ファイル名とエンコーディングを受け取り、promise オブジェクトを返す関数を作成するという同じ目標read2を達成します。read3

それらについては、これを行うことができます:

read2('file.txt', 'utf8').then(function (data) {}, function (err) {}).done();
read3('file.txt', 'utf8').then(function (data) {}, function (err) {}).done();

の場合read1、次のように呼び出します。

read1('file.txt', 'utf8', function (data) {}, function (err) {});

アップデート

これが回答されて以来、標準の約束は少し進化しましたread3

var read4 = function (fname, enc) {
    return Q.promise(function(resolve, reject){
        fs.readFile(fname, enc, function (error, text) {
            if (error) {
                // 'error' is already an error object, you don't need 'new Error()'.
                reject(error);
            } else {
                resolve(text);
            }
        });
    });
};

これは、標準の ES6 の約束や bluebird とより一致しているため、コードを進めやすくなります。で説明した方法を使用するread3と、通常は望ましくないプロミス チェーンで例外をキャプチャする代わりに、例外を同期的にスローする可能性も生じます。遅延アンチパターンを参照してください。

于 2013-02-20T17:43:30.293 に答える