2017-09-29 2 views
0

Ich lerne Knoten und verspricht. Ich habe mein Problem vereinfacht und meinen Code unten geteilt.asynchrone Codierung mit Versprechen

Ich habe drei Module: app.js, modLanguage.js und model.js

app.js:

var l = require('../test/modLanguage.js'); 

var params = [{ 
    p0: 'johnDoe', 
    p1: '12345', 
    p2: 0 
}]; 

var lang = l.call(params); 
console.log("Needs to run last: " + lang.language); 

modLanguage.js:

var call = function(params) { 
    var langQuery = require('../test/model.js'); 
    var userLang = createLanguage(); 

    userLang.setLanguage('FRENCH'); 
    console.log("This needs to run first - setting lang French before DB dip: " + userLang.language); 

    var myData = langQuery.getLanguage(params) 
     // My DB dip 
     .then(function(data) { 
      var data = JSON.parse(JSON.stringify(data[0])); 
      userLang.setLanguage(data[0].Language); 
      console.log("Needs to run second - DB dip brought language ENG: " + userLang.language); 
      return userLang; 
     }) 
     .catch(function(err) { 
      console.log('error'); 
     }); 
    return userLang; 
} 
module.exports.call = call; 


function createLanguage() { 
    return { 
     language: this.language, 
     setLanguage: function(language) { 
      this.language = language; 
      return this.language; 
     } 
    } 
} 

model.js ist ein einfaches Modul, das params verwendet, eine gespeicherte Prozedur ausführt und Daten durch Rückgabe eines Versprechens zurückbringt.

Ich möchte die Ausführung von Code an app.js blockieren, bis das Objekt aus den Daten gegen Datenbank Dip initialisiert wird. Doch wie ist die console.log zeigt:

Dies muss zuerst ausgeführt werden - Einstellung lang Französisch vor DB dip: FRENCH

Needs laufen zuletzt: FRENCH

Needs an zweiter Stelle laufen - DB Dip gebracht Sprache ENG: ENG

Was ich will, erreichen, ist offensichtlich:

Dies muss zuerst ausgeführt werden - Einstellung lang Französisch vor DB dip: FRENCH

Needs an zweiter Stelle laufen - DB Dip gebracht Sprache ENG: ENG

Needs zuletzt laufen: ENG

Bitte, Beratung die Veränderungen, die ich machen muss, um das zu erreichen?

+2

Sie benötigen ein Versprechen zurückzukehren, von 'call' wenn Sie darauf warten wollen in' app.js' ... und verwenden '.then' in' app.js' weil Sie im Moment Promises nicht richtig verwenden –

Antwort

1

Hier sind die Zeilen, die geändert werden müssen, und warum.

// Instead of assigning this promise to a variable that you never 
// even use, just return the promise to the caller, so caller can wait 
// for a result to actually be there. 

return langQuery.getLanguage(params) 

// Returning userLang will cause your app to process userLang 
// before you've attached the proper language to it. Don't return 
// it. Instead, return the promise that tells you userLang will 
// be ready, as described above. 

return userLang; // delete this line 


// Now that the promise is returned instead of an incomplete 
// object, we can wait for the promise to resolve before logging. 

var lang = l.call(params).then(lang => 
    console.log("Needs to run last: " + lang.language) 
); 


Hier ist ein funktionierendes Schnipsel zu demonstrieren.

Als Nebenbemerkung, var ist im Wesentlichen veraltet zugunsten let, die sich fast genau gleich verhält, außer für ein Update für einige Gotcha! Scoping-Verhalten.

Ich denke, mit const besser ist als let für jede Zuweisung in diesem Beispiel wird aber let hier in Ihrem Namen zu verwenden, da es weg ein viel kleinerer Schritt ist var verwenden.

Wenn Sie in einem Code-Basis arbeiten, die Sie var verwenden zwingt, stellen Sie sicher, dass Sie die Unterschiede zwischen Forschung var/let, sonst verlassen nur mit var und Ihr Leben wird es schöner sein.

/** some mock-ups to make the example run in a snippet **/ 
 

 
const module = {exports: {}} 
 

 
let modelMock = { 
 
    getLanguage(params){ 
 
     return Promise.resolve([[{ 
 
      Language: 'en-us' 
 
     }]]) 
 
    } 
 
} 
 

 
function require (path) { 
 
    if (path === '../test/model.js') 
 
     return modelMock; 
 
    if (path === '../test/modLanguage.js') 
 
     return module.exports; 
 
} 
 

 
/********* log to output pre instead of console *********/ 
 

 
console.log = (...args) => 
 
    [...args].forEach(arg => 
 
     document.querySelector('pre').innerText += '\n' + arg 
 
); 
 

 
/******************* modLanguage.js *********************/ 
 

 
let call = function(params) { 
 
    let langQuery = require('../test/model.js'); 
 
    let userLang = createLanguage(); 
 

 
    userLang.setLanguage('FRENCH'); 
 
    console.log(
 
     'This needs to run first - setting lang French before DB dip: ' 
 
     + userLang.language 
 
    ); 
 

 
    return langQuery.getLanguage(params) 
 
     // My DB dip 
 
     .then(function(data) { 
 
      // JSON.parse is known to throw. We should always wrap it 
 
      // in a try catch block and decide how to deal with the error. 
 
      // In this case, I'm just rethrowing with clearer message. 
 
      try { data = JSON.parse(JSON.stringify(data[0])); } 
 
      catch(e) { 
 
       e. message = 
 
        'langQuery.getLanguage could not parse provided data'; 
 
       throw e; 
 
      } 
 
      
 
      userLang.setLanguage(data[0].Language); 
 
      
 
      console.log(
 
       'Needs to run second - DB dip brought language ENG: ' 
 
       + userLang.language 
 
      ); 
 
      
 
      return userLang; 
 
     }) 
 
     .catch(function(err) { 
 
      console.error('error'); 
 
     }); 
 
} 
 

 

 
module.exports.call = call; 
 

 
function createLanguage() { 
 
    return { 
 
     language: this.language, 
 
     setLanguage: function(language) { 
 
      this.language = language; 
 
      return this.language; 
 
     } 
 
    } 
 
} 
 

 
/************************ app.js ************************/ 
 

 
let l = require('../test/modLanguage.js'); 
 

 
let params = [{ 
 
    p0: 'johnDoe', 
 
    p1: '12345', 
 
    p2: 0 
 
}]; 
 

 
l.call(params).then(lang => 
 
    console.log("Needs to run last: " + lang.language) 
 
);
<pre></pre>

+0

Hallo, ich habe die Änderungen gemacht, die Sie vorgeschlagen haben, aber das letzte Bit wird nie aufgerufen. Ich habe versucht, den neuesten Code hinzuzufügen, aber es ist zu lang wie ein Kommentar – Ben77

+0

Nicht sicher, wo Ihr Problem dann ist. Ich habe ein ausführbares Snippet Ihres Beispiels hinzugefügt, das sich wie erwartet verhält. – skylize

+0

Danke! Es funktioniert genau so, wie ich es erwartet habe und die Nuance von let/var/const ist das i-Tüpfelchen - gibt mir eine Richtung, worauf ich als nächstes forschen/arbeiten soll. Mit dem von mir bereitgestellten Code werde ich auch meine Fehler rückverfolgen. – Ben77

0

Sie könnten ein Versprechen von call zurückgeben. Anstatt lang direkt mit dem Rückgabewert zu setzen, tun Sie l.call(...).then(...); und machen Sie Ihren letzten Anruf und setzen Sie lang in den Rückruf.

+0

Ich habe das vor dem Posten auch versucht ... Aber ich bin verloren auf was zu tun/ändern auf app.js. Könnten Sie bitte ein Beispiel für den von mir bereitgestellten Code geben? – Ben77

Verwandte Themen