Wie sende ich aus einer verschachtelten Funktion im Knoten an einen EventListener.js (Javascript-Scoping-Problem)

StackOverflow https://stackoverflow.com//questions/9631989

  •  10-12-2019
  •  | 
  •  

Frage

Ich schreibe unten Code, der nacheinander eine Site-API analysiert, und teilt dann einer Ereigniswarteschlange mit, dass sie für das nächste zu analysierende Objekt bereit ist.Ich habe Probleme, da ich noch neu im Javascript-Bereich bin und von SiteParser ausgeben oder die Funktion emitForNext aufrufen möchte.Ich kann emitForNext im Fehlerrückruf anscheinend nicht in den Gültigkeitsbereich bringen.

   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);
            });
        };
    }
War es hilfreich?

Lösung

JavaScript hat Funktionsumfang. Wenn Sie eine Variable mit dem Schlüsselwort var deklarieren, ist sie lokal für die aktuelle Funktion.Wenn Sie auf eine Variable zugreifen, wird auf die Bereichskette geschaut, die aus der aktuellen Funktion, der übergeordneten Funktion, ....Versuchen:

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()

Meistens definieren wir Variablen am Anfang von Funktionen, weil eine im Funktionskörper definierte Variable gehisst wird.Grundsätzlich bedeutet dies, dass es in der gesamten Funktion verfügbar ist, noch bevor es definiert wurde, aber in diesem Fall ist es der Wert undefined.

Wenn zum Beispiel eine Variable nicht definiert ist, erhalten wir normalerweise eine ReferenceError, aber im folgenden Ausschnitt beide console.log() einfach drucken undefined.

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

Eine gängige Praxis ist also, dass Sie dies beim Schreiben langer Funktionen sich selbst zuordnen.

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

Sie sollten nicht alle Ihre Methoden in den Konstruktor schreiben, es ist nur manchmal nützlich, wenn wir Privatsphäre wollen, aber in diesem Fall sollten Sie besser Prototypen verwenden.

Wenn ich das zusammenfasse, würde ich schreiben:

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);
    });
};

Andere Tipps

Um auf emitForNext zugreifen zu können, müssen Sie anrufen self.emitForNext, wo self verweist auf Ihre Instanz von SiteParser.

Wie so:

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);

        });

    };

}

Es sieht jedoch so aus, als würden Sie lieber verwalten, was Sie als nächstes tun (z. B. das Parsen des nächsten Objekts) in Ihrem Rückruf, dh.im Körper von processJSON.

Sie müssen den Link zu 'diesen' 'Objekt in Siteparser lokalem Umfang speichern. generasacodicetagpre.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top