1

nodejs で promise を使用しようとしています (node-promise パッケージで試しています)。しかし、何の成功もありません。以下のコードを参照してください。

var express = require('express'),
    request = require('request'),
    promise = require('node-promise');

app.get('/promise', function(req, res) {
    var length = -1;

    new promise.Promise(request(
        {uri: "http://www.bing.com"},
        function (error, response, body) {
            if (error && response.statusCode !== 200) {
                console.log("An error occurred when connected to the web site");
                return;
            }

            console.log("I'll return: " + body.length);
            length = body.length;
        }
    )).then(function(result) {
        console.log("This is what I got: " + length);
        console.log("Done!");
    });

    res.end();
});

上記コードの出力I'll return: 35857のみで、その部分には行きませんthen

次に、コードを次のように変更します。

app.get('/promise', function(req, res) {
    var length = -1;

    promise.when(
        request(
            {uri: "http://www.bing.com"},
            function (error, response, body) {
                if (error && response.statusCode !== 200) {
                    console.log("An error occurred when connected to the web site");
                    return;
                }

                console.log("I'll return: " + body.length);
                length = body.length;
            }
        ),
        function(result) {
            console.log("This is what I got: " + length);
            console.log("Done!");
        },
        function(error) {
            console.log(error);
        }
    );

    res.end();
});

今回の出力はThis is what I got: -1...今回Done!は「約束」が呼び出されなかったようです。

そう:

  • 上記のコードを修正するには何が必要ですか? 明らかに私はそれを正しくやっていません:)
  • 私が約束をしているとき、node-promiseは「行くべき道」ですか、それともより良い方法/パッケージがありますか? つまり、よりシンプルで、より本番環境に対応しています。

ありがとう。

4

2 に答える 2

4

jquery-deferred-for-node を試してください。

私は専門家ではありませんが、このライブラリがサーバー側とクライアント側の両方で作業するプログラマーに好まれる傾向があることは理解しています。

jQuery の Deferreds をまだ知らない場合でも、このルートを使用する利点は次のとおりです。

  • Node.js 固有の例を見つけるのに苦労するかもしれませんが、ドキュメントは優れています (jQuery ドキュメントへのリンクが含まれています)。

  • メソッドは連鎖可能です。

  • jQueryCallbacksも含まれています。

  • ある日、クライアント側で非同期処理を行う必要が生じた場合でも、再学習する必要はほとんどありません。概念は同じであり、構文もほぼ同じです。上記のハイパーリンクでリンクされた github ページの「対応」セクションを参照してください。

編集

私はnode.jsの人ではないので、ここで推測していますが、上記のコードに基づいて、 jquery-deferred-for-node を使用して次の行に沿って何かを検討することをお勧めします:

var express = require('express'),
    request = require('request'),
    Deferred = require('JQDeferred');

function fetch(uri, goodCodes) {
    goodCodes = (!goodCodes) ? [200] : goodCodes;

    var dfrd = Deferred(); // A Deferred to be resolved/rejected in response to the `request()`.
    request(uri, function(error, response, body) {
        if (!error) {
            var isGood = false;

            // Loop to test response.statusCode against `goodCodes`.
            for (var i = 0; i < goodCodes.length; i++) {
                if (response.statusCode == goodCodes[i]) {
                    isGood = true;
                    break;
                }
            }

            if (isGood) {
                dfrd.resolve(response.statusCode, body);
            } else {
                dfrd.reject(response.statusCode, "An invalid response was received from " + uri);
            }
        } else {
            dfrd.reject(response.statusCode, "An error occurred attempting to connect to " + uri);
        }
    });

    // Make promise derived from dfrd available to "consumer".
    return dfrd.promise();
};

//...

app.get('/promise', function(req, resp) {
    fetch("http://www.bing.com").done(function(statusCode, result) {
        console.log("Done! This is what I got: " + result.length);
    }).fail(function(statusCode, message) {
        console.log("Error (" + statusCode + "): " + message);
    });
    resp.end();
};

ここでは、非同期応答 (またはエラー) を外部で処理できるように、リソースを取得するための一般化されたユーティリティを作成しようとしました。これは、あなたが達成しようとしていたことに大まかに沿っていると思います。

興味深いことに、console.log() メッセージは node.js でどこに行き着くのでしょうか?

編集2

上記ではDeferred、コンストラクターの慣例として、初期資本を指定しました

jQuery Deferreds では、連続して fetch() する方法がいくつも必要です。以下のアプローチはそのままにして、フロントエンドとして機能するようにfetch()導入します。fetch_()もっと簡単な方法があるかもしれませんが、これによりfetch()、クライアント側と機能的に同等の一般的なユーティリティのままにすることができますjQuery.ajax()

function fetch_(uri){
    return function(){
        return fetch(uri, [200]).then(function(statusCode, result){
            console.log("Done! This is what I got: " + result.length);
        },function(statusCode, message){
            console.log("Error (" + statusCode + "): " + message);
        });
    };
}

fetch()function は関数を返すことに注意してください。wherefetch()が呼び出されたとき、(まだ) その関数の結果ではなく、実行されていない関数が必要なため、このようにする必要があります。

ここで、uris の配列が利用可能であると仮定しましょう。これは、ハードコーディングすることも、動的に構築することもできます - アプリケーションが要求するものは何でも。

var uris = [
    'http://xxx.example.com',
    'http://yyy.example.com',
    'http://zzz.example.com'
];

そして今、さまざまな方法で をfetch_()呼び出すことができます:

//v1. To call `resp.end()` when the fetching process starts.
app.get('/promise', function(req, resp) {
    fetch_(uris[0])().then(fetch_(uris[1])).then(fetch_(uris[2]));
    resp.end();
});

//v2. To call `resp.end()` when the fetching process has finished.
app.get('/promise', function(req, resp){
    fetch_(uris[0])().then(fetch_(uris[1])).then(fetch_(uris[2])).always(resp.end);
});

//v3. As v2 but building a `.then()` chain of any (unknown) length.
app.get('/promise', function(req, resp){
    var dfrd = Deferred().resolve();//
    $.each(uris, function(i, uri){
        dfrd = dfrd.then(fetch_(uri));
    });
    dfrd = dfrd.always(resp.end);
});

テストされていない

v1 と v2 には自信があります。v3 が動作する可能性があります。

v2 と v3 はどちらもまったく同じ動作をするはずですが、v3 は任意の数の URI に対して一般化されています。

すべてにデバッグが必要な場合があります。

于 2012-12-22T10:21:24.913 に答える
3

Q: https://github.com/kriskowal/qを使用することをお勧めします。他のフレームワーク (jQuery の遅延実装など) によって内部的に使用されていると思います。

ドキュメントは「問題ない」と思います。構文は他のプロミスの実装と一致しています...そしてノードアダプターがあります。

したがって、遅延スタイルのアプローチ:

var deferred = Q.defer();
FS.readFile("foo.txt", "utf-8", function (err, res) {
    if (!err) {
        deferred.resolve(res);
    } else {
        deferred.reject(err);
    }
});
return deferred.promise;

より簡潔に次のように記述できます。

var deferred = Q.defer();
FS.readFile("foo.txt", "utf-8", deferred.makeNodeResolver());
return deferred.promise;
于 2013-01-19T19:59:14.900 に答える