2

次のオブジェクトを解析する準備ができていることをイベント キューに伝えるよりも、サイト API を一度に 1 つずつ解析するコードを以下に書いています。私はまだ JavaScript スコープに慣れていないため、問題が発生しています。SiteParser から出力するか、emitForNext 関数を呼び出したいと考えています。エラーコールバックでemitForNextをスコープに入れることができないようです。

   function SiteParser(){
        this.emitForNext = function  (message) {
            this.emit("next", message);
        };

        this.pullJSON = function (path, processJSON) { //processJSON is a callback function    
            var options = {
                host: 'www.site.com',
                port: 80,
                path: path
            }

            //console.log("... processing "+path); 

            //pulls the entire json request via chunks
            http.get(options, function  (res) {
                var resJSON = ''; //stores the comment JSON stream given in the res
                res.on('data',  function (chunk) {
                    resJSON+=chunk;   
                });  
                res.on('end', function () {
                    var obJSON = (JSON.parse(resJSON));  

                    if (obJSON.hasOwnProperty("error")){ 
                        console.log(obJSON);
                        console.log('... ', path, ' does not exist');
                        //
                        //NEED A NEXT EVENT EMMITER HERE NEED TO FIGURE OUT SCOPE
                        //
                        //   
                    } else {
                        processJSON(obJSON); //call the callback function
                    }
                }) ;
            }).on('error', function  (e) {
                emitForNext("got error: " + e.message);
            });
        };
    }
4

3 に答える 3

4

JavaScript には関数スコープがあり、var キーワードで変数を宣言すると、現在の関数に対してローカルになります。変数にアクセスすると、現在の関数で構成されるスコープ チェーンが参照されます。これは親関数です。試す:

function one() {
    var foo = 'foo';

    function two() {
        console.log(foo) // undefined. I'll explain this
        var foo = 'bar';
        console.log(foo) // bar
    }

    two()
    console.log(foo) // foo
}
one()

関数の本体で定義された変数は巻き上げられるため、ほとんどの場合、関数の先頭で変数を定義します。基本的には、定義される前でも関数全体で使用できることを意味しますが、この場合の値はundefinedです。

たとえば、変数が定義されていない場合、通常は を取得しますが、ReferenceError以下のスニペットでは両方ともconsole.log()単に を出力しますundefined

function foo() {
     console.log(bar);
     if (0) {
         var bar = 'bar';
     }
     console.log(bar);
}

したがって、長い関数を記述するときは、これを自分自身にマップするのが一般的な方法です。

function SiteParser() {
    var self = this;
    // ...
    .error('error', function(err) {
        self.emitForNext("got " + err.message);
    })
}

すべてのメソッドをコンストラクターに記述する必要はありません。プライバシーが必要な場合にのみ役立ちますが、この場合はプロトタイプを使用することをお勧めします。

これをまとめると、次のように書きます。

var SiteParser = function() {};

SiteParser.prototype.emitForNext = function(message) {
    this.emit("next", message);
};

SiteParser.prototype.pullJSON = function(path, processJSON) { 
    var self    = this,
        options = {
            host: 'www.site.com',
            port: 80,
            path: path
        };

    http.get(options, function(res) {
        // ...
    }).on('error', function  (e) {
        self.emitForNext("got error: " + e.message);
    });
};
于 2012-03-09T10:45:58.933 に答える
2

emitForNext にアクセスできるようにするには、SiteParser のインスタンスを指す を呼び出す必要がありself.emitForNextますself

そのようです:

function SiteParser(){

    this.emitForNext = function  (message) {

        this.emit("next", message);

    };



    this.pullJSON = function (path, processJSON) { //processJSON is a callback function    

        var options = {

            host: 'www.site.com',

            port: 80,

            path: path

        };



        var self = this;



        //console.log("... processing "+path); 



        //pulls the entire json request via chunks

        http.get(options, function  (res) {

            var resJSON = ''; //stores the comment JSON stream given in the res

            res.on('data',  function (chunk) {

                resJSON+=chunk;   

            });  

            res.on('end', function () {

                var obJSON = (JSON.parse(resJSON));  



                if (obJSON.hasOwnProperty("error")){ 

                    console.log(obJSON);

                    console.log('... ', path, ' does not exist');





                    self.emitForNext(path + ' does not exist');

                } else {

                    self.emitForNext('Successfully parsed the response');

                    processJSON(obJSON); //call the callback function

                }

            }) ;

        }).on('error', function  (e) {

            self.emitForNext("got error: " + e.message);

        });

    };

}

ただし、コールバックで次に行うこと (次のオブジェクトの解析など) を管理したいようです。の本体でprocessJSON

于 2012-03-09T10:43:49.073 に答える
1

「この」オブジェクトへのリンクを SiteParser ローカル スコープに保存する必要があります。

 function SiteParser () {
    var that = this; // store link to 'this' in local scope

    this.emitForNext = function (message) {
        this.emit("next", message);
    };

    this.pullJSON = function (path, processJSON) { //processJSON is a callback function    
        var options = {
            host: 'www.site.com',
            port: 80,
            path: path
        }

        //console.log("... processing "+path); 

        //pulls the entire json request via chunks
        http.get(options, function  (res) {
            var resJSON = ''; //stores the comment JSON stream given in the res
            res.on('data',  function (chunk) {
                resJSON+=chunk;   
            });  
            res.on('end', function () {
                var obJSON = (JSON.parse(resJSON));  

                if (obJSON.hasOwnProperty("error")){ 
                    console.log(obJSON);
                    console.log('... ', path, ' does not exist');
                    that.emitForNext();
                } else {
                    processJSON(obJSON); //call the callback function
                }
            }) ;
        }).on('error', function (e) {
            that.emitForNext("got error: " + e.message);
        });
    };
}
于 2012-03-09T10:43:03.323 に答える