2016-09-24 4 views
0

Ich habe eine formidable Form, die die Anfrage analysieren. Dann wird zusammen mit dieser Anfrage die Datei hochgeladen. In formidable können Sie ein Ereignis anhören, wenn es eine Datei gibt.Javascript: Wie auf lokale Variable in Callback-Funktion zugreifen?

var form = new formidable.IncomingForm({ 
    uploadDir: __dirname + '/temp', 
    keepExtensions: true 
}); 

Dies ist, wo ich auf das Ereignis

form.on('file', function(name, file){ 
    var file = file; 
    fs.readFile(file.path, readFileCallback); 
}); 

function readFileCallback(err, contents){ 
    console.log(file); 
    if (err) throw err; 
    .... 
} 

Mein erster Code eine Kette von Callback-Funktionen zu hören und es ist ziemlich schwer, so zu lesen und zu pflegen, war ich mit diesem Ansatz wechseln, wo ich würde Funktionen erklären sie dann als Rückruf anrufen, anstatt wie folgt aus:

form.on('file', function(name, file){ 
    fs.readFile(file.path, function(err, contents){ 
     console.log(file); 
     if (err) throw err; 
     .... 
    }); 
}); 

Mit dieser Art von Ansatz, ich könnte die außen zugreifen Variable, die file ist. Ich frage mich, was ist der Unterschied zwischen den beiden beim Zugriff auf die äußeren Variablen. Danke im Voraus.

+0

Die erste wird innerhalb des Bereichs der übergeordneten Funktion definiert, sodass Zugriff auf die lokalen Variablen der umschließenden Funktion besteht. Der zweite ist außerhalb definiert und nicht eingeschlossen. – gurvinder372

+0

Eng verwandt: [* Wie funktionieren JavaScript-Verschlüsse? *] (Http://stackoverflow.com/questions/111102/how-do-javascript-closures-work?rq=1) –

Antwort

1

Es ist eine Frage von Scope. Code hat Zugriff auf die Variablen, die in der Funktion deklariert sind, auf ihre enthaltene Funktion (falls vorhanden), auf ihre enthaltene Funktion (falls vorhanden) usw. und dann auf globale Variablen.

In Ihrem ersten Beispiel ist readFileCallback außerhalb des Rückrufs form.on deklariert, und so hat es keinen Zugriff auf die Dinge in der form.on Rückruf.

In Ihrem zweiten Beispiel ist die Funktion innerhalb der form.on Rückruf, und so hat es Zugriff auf die Dinge darin.

Beachten Sie, dass im zweiten Beispiel in der Theorie eine neue Funktion jedes Mal erstellt wird, wenn der Rückruf aufgerufen wird. Das ist in Ordnung, JavaScript-Engines sind wirklich schnell beim Erstellen von Funktionen (und gute werden den Code wiederverwenden, obwohl ein separates Funktionsobjekt erstellt wird).

Normalerweise möchten Sie die Funktion an der äußersten Stelle erstellen, wo sie Zugriff auf alles hat, was sie benötigt. Also in Ihrem Fall wäre das innerhalbform.on, aber außerhalb der readFile Rückruf. Welches ist genau, wo dein zweites Beispiel es hat. Aber Sie können eine benannte Funktion wie Ihr erstes Beispiel, wenn Sie möchten, setzen Sie es nur inform.on ‚s Rückruf:

form.on('file', function(name, file){ 
    fs.readFile(file.path, readFileCallback); 
    function readFileCallback(err, contents){ 
     console.log(file); 
     if (err) throw err; 
     .... 
    } 
}); 

Nehmen wir ein Beispiel nehmen, wo alles einen einfachen Namen hatte, und folgen Sie durch zwei Anrufe:

function outer(outerArg) { 
    function middle(middleArg) { 
     function inner(innerArg) { 
      console.log("innerArg = " + innerArg); 
      console.log("middleArg = " + middleArg); 
      console.log("outerArg = " + outerArg); 
     } 

     inner(middleArg.toLowerCase()); 
    } 

    middle(outerArg.toUpperCase()); 
} 

outer enthält middle die inner und outermiddle Anrufe (Anrufe und middleinner) enthält.Ein Aufruf:

outer("Test1"); 
  1. outer bekommt das ARG "Test1"
  2. Es ruft middle mit "TEST1"
  3. Es ruft inner mit "test1"
  4. inner Ausgänge:

     
    innerArg = test1 
    middleArg = TEST1 
    outerArg = Test1 
    

So weit, so einfach, aber es ist spannender als das: Was passiert, wenn middle eine Funktion zurückgibt, die inner aufruft, anstatt sie sofort zu rufen, und outer kehrt zurück middle ‚Rückgabewert s?

function outer(outerArg) { 
    function middle(middleArg) { 
     function inner(innerArg) { 
      console.log("innerArg = " + innerArg); 
      console.log("middleArg = " + middleArg); 
      console.log("outerArg = " + outerArg); 
     } 
     function caller() {       // *** 
      inner(middleArg.toLowerCase());   // *** 
     }           // *** 
     return caller;        // *** 
    } 

    return middle(outerArg.toUpperCase());   // *** 
} 

Nun ruft outer keine Ausgabe überhaupt haben:

var f = outer("Test2"); 

Aber dann Aufruf der Funktion middle zurückgegeben (caller) tut:

f(); 

Ausgang:

 
innerArg = test2 
middleArg = TEST2 
outerArg = Test2 

Die Argumente existieren noch nach outer und middle zurück! Aber es ist noch interessanter:

var f1 = outer("Test3"); 
var f2 = outer("Test4"); 
f2(); // Note -- calling the second one first 
f1(); 

Ausgang:

 
innerArg = test4 
middleArg = TEST4 
outerArg = Test4 
innerArg = test3 
middleArg = TEST3 
outerArg = Test3 

Das heißt also,, zweiouterArg s noch existierte, nachdem beide Anrufe zu outer fertig war, zusammen mit zweimiddleArgs. Wie?

Sie existieren auf Objekte auf die Funktionen angehängt:

  • outer Aufruf erzeugt ein Ausführungskontext (ein Objekt), die unter anderem (und eine Menge Details Weglassen) die Argumente und lokale hält Variablen für diesen Aufruf an outer. Nennen wir es den "äußeren Kontext". Es hat auch einen Verweis auf den Ausführungskontext, der es enthält (der globale Kontext in unserem Code). Normalerweise wird dieses Objekt aufgeräumt, wenn ein Functon zurückkehrt ...
  • ... aber outer erstellt eine Funktion, middle. Wenn Sie eine Funktion erstellen, wird der aktuelle Ausführungskontext an die Funktion angehängt. So hat es Zugriff auf die Variablen und so in diesem äußeren Kontext.
  • outer ruft middle, einen inneren Ausführungskontext zu schaffen und middle erzeugt zwei andere Funktion (inner und caller), die jeweils erhalten, dass die innere Rahmen mit ihnen verbunden.middle dann gibtcaller zurück, so caller existiert, nachdem der Anruf zu middle abgeschlossen ist. Da caller einen Verweis auf den inneren Ausführungskontext hat, besteht der Kontext weiterhin (genau wie jedes andere Objekt), obwohl middle zurückgegeben wurde. Da dieser Zusammenhang eine Bezugnahme auf inner, innerhat, existiert auch weiter bestehen.
  • outer gibt den Rückgabewert von middle (die caller ist), und so besteht das bedeutet caller noch, wenn outer zurückgibt, das heißt, den inneren Zusammenhang noch bezieht sich auf existiert, die inner noch Mittel vorhanden ist, und der äußere Rahmen existiert immer noch, weil der innere Kontext einen Bezug darauf hat.

... das ist, wie f1 und f2 Zugriff auf diese Argumente haben nach outer zurückkehrt: Wenn man sie laufen, sie sehen die Werte in den Kontexten oben mit ihnen verbunden.

+0

In diesem Fall würde ich nur erstellen meine Funktion innerhalb des 'Ereignisses', um Zugang zu den 'form.on' Variablen zu haben? –

+0

@JMSantos: Das stimmt. –

+0

Aha! Jetzt bekomme ich die Variablen außerhalb meiner Funktionen. Danke, mein Herr. –

Verwandte Themen