2016-04-12 14 views
2

私はこのコードをデータベースに複数回要求することで得たデータを含む応答を送信したいのです。私はなぜそれが空の応答を送信するのか分かりません。jsonレスポンスの作成。 NodeJSは空の応答を送信します

var express = require('express'), 
router = express.Router(), 
database = require('../database'); 

router.get('/', function(req, res, next){ 

    res.writeHead(200, {"Content-Type": "application/json"}); 

    var ttt; 
    var yyy; 

    database.getTagType().then(function(data) { 
     ttt = "pfff"; 
    }); 

    database.getSpecie().then(function(data) { 
     yyy = "akkhhh"; 
    }); 

    var json = JSON.stringify({ 
    anObject: ttt, 
    anArray: yyy, 
    }); 
    res.end(json); 

}); 

module.exports = router; 
+0

約束は非同期であるので、あなたはあなたの応答のための 'json'オブジェクトを作成するときに' 'ttt'とyyy'がまだ割り当てられていない。このコードは、クリーナーを取得 – arthurakay

答えて

4

この問題は非同期性のため、Promise.thenです。あなたは、両方の約束が解決される前に、JSON.stringifyres.endが呼び出されていることがわかります。すべてのデータが取得されたときにのみ応答を送信するには、Promise.allメソッドを使用する必要があります。ここで

は、それが行うことができる方法の例です:

router.get('/', function(req, res, next){ 
    var promises = []; 

    promises.push(database.getTagType().then(function(data){ 
     return "pfff"; 
    })); 

    promises.push(database.getSpecie().then(function(data) { 
     return "akkhhh"; 
    })); 

    Promise.all(promises).then(function(values) { 
     // Actually, express can stringify response for us. Also it adds 
     // correct "Content-Type" header. 
     res.json({ 
      anObject: values[0], 
      anArray: values[1] 
     }); 
    }).catch(function(error) { 
     // Something went wrong. Let the error middleware deal with the problem. 
     next(error); 
     // Instead we can just send an error response, like so: 
     // res.status(500).json({error: error.toString()}); 
    }); 
}); 
+1

'catch'ブロックを追加してください。あなたの現在のコードでは、エラーが発生した場合、ユーザは決して応答を受け取らないからです。 – alexmac

+0

あなたはそうです、通知ありがとうございます。私は答えを更新しました。 –

+0

清算していただきありがとうございます。 – Soumia

1

データベース呼び出しは非同期です。彼らは約束を返すし、あなたはthen関数を追加していますが、javascriptの実行方法は、関数がres.end()と応答を送信してからの前に約束が解決され、dbコールが終了します。

応答で返信する前にすべての約束が解決するのを待つことを確認する必要があります。これは本質的にはthen()機能のネストを必要とします。

ようなので:

router.get('/', function(req, res, next){ 

    res.writeHead(200, {"Content-Type": "application/json"}); 

    var tag = database.getTagType(); 
    // `tag` is now a promise 

    var specie = database.getSpecie(); 
    // `specie` is a promise 

    Promise.all([tag, specie]).then(function(values) { 
    // this code is executed once both promises have resolved, the response has come back from the database 

     var json = JSON.stringify({ 
      tag: values[0], 
      specie: values[1] 
     )}; 

     res.end(json); 
    }); 
}); 

この関数はすぐに戻りますが、データベース・コールが完了するまでres.end()を呼び出すことはありません。

async/awaitが言語に追加された後:)

+0

ありがとうございます。問題が解決しました – Soumia

+0

@ user2795508回答が「承諾済み」と表示され、解決済みであることが分かりますか?答えの横にチェックマークを入れる必要があります。 – TinyTimZamboni

+0

私はそれをチェックしました、ありがとう;) – Soumia

関連する問題