2017-09-29 20 views
0

私はノードと約束を学んでいます。私は私の問題を単純化し、私のコードを以下に共有しました。 app.js、modLanguage.jsと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は、paramsを使用し、ストアドプロシージャを実行し、約束を返してデータを戻す単純なモジュールです。

データベースdipから返されたデータからオブジェクトが初期化されるまで、app.jsでコードの実行をブロックします。しかし、であるとして、にconsole.logは示しています

これは、最初に実行する必要がある - DBのディップ前にLANGフランス語を設定する:最後に実行するFRENCH

必要があります。第二に実行するFRENCH

ニーズ - DBディップもたらした言語ENG:ENG

は何を達成したいことは明らかである:

これは、最初に実行する必要がある - DBのディップ前にLANGフランス語を設定する:第二に実行するFRENCH

ニーズ - DBディップもたらした言語ENG:ENG

ニーズを最後に実行する:ENG

してください、アドバイスそれを達成するために必要な変更は?

+2

あなたが約束を正しく使用していない瞬間に –

答えて

1

変更が必要な行とその理由は次のとおりです。ここで

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


実証する作業スニペットです。

脇の下として、varは本質的に、letの方が推奨されていません。ほとんどの場合同じように動作しますが、いくつかの問題を修正しました!スコープの振る舞い。

私はconstを使用すると、この例では、すべての代入文についてletよりも優れているが、それは離れてvarを使用してからずっと小さなステップだから、あなたに代わって、ここletを使用すると思います。

、あなたがvar/letの違いを研究していることを確認した後、varを使用するように強制的にコードベースで作業している場合は、それ以外の場合はちょうどvarを使用して終了し、あなたの人生はそれのためのよりよいだろう。あなたはapp.js` `でそれを待ちたい場合call``からの約束を返す...とapp.js` `で` .then`を使用する必要が

/** 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

こんにちは、私は最後のビットが呼び出されることはありませんが、あなたが提案した変更を加えました。私は最新のコードを追加しようとしましたが、コメントとして長すぎます – Ben77

+0

あなたの問題がどこにあるのか不明です。私はあなたの例の実行可能なスニペットを追加して、期待どおりに動作します。 – skylize

+0

ありがとうございます!私の期待通りに機能し、/ var/constがケーキのアイシングであることについてのニュアンスがあります - 私は次に何を研究/作業するかについて私に指示を与えます。提供されたコードを使用して、エラーを再トレースします。 – Ben77

0

callから約束を返すことができます。 langを戻り値で直接設定する代わりに、l.call(...).then(...);を実行し、最後の呼び出しを行い、コールバック内にlangを設定します。

+0

私はそれを投稿する前にそれを試みました...しかし、私は何をするか/ app.jsで変更することに迷っています。私が提供したコードの例を教えてください。 – Ben77