2017-01-06 9 views
0

私はnodejs/expressjsとmongodbを初めて使用しています。私は、Ionicフレームワークを使用して構築しようとしているモバイルアプリケーションにデータを公開するAPIを作成しようとしています。NodeJS/ExpressJSのルータコールバックに約束を返す方法

私はMongoDBのデータを読み込み、私のモデルで機能を持っているこの

router.get('/api/jobs', (req, res) => { 
    JobModel.getAllJobsAsync().then((jobs) => res.json(jobs)); //IS THIS THe CORRECT WAY? 
}); 

のようなルートを設定しています。私は、私のモデル関数を約束を返すように変換するBluebird約束ライブラリを使用しています。モデルで

const JobModel = Promise.promisifyAll(require('../models/Job')); 

My機能

static getAllJobs(cb) { 

    MongoClient.connectAsync(utils.getConnectionString()).then((db) => { 

     const jobs = db.collection('jobs'); 
     jobs.find().toArray((err, jobs) => { 

     if(err) { 
      return cb(err); 
     } 

     return cb(null, jobs); 
     }); 
    }); 
    } 

promisifyAll(MyModuleという)は約束を返すために、この機能を変換します。これは私のモデルからのルートコールバック関数にデータを返すための正しいアプローチであるならば、私はわからない何

は、

  • のですか?
  • これは効率的ですか?
  • promisifyAllの使用は遅いですか?これはモジュール内のすべての関数をループし、Asyncを接尾辞として使用して将来の約束を返す関数のコピーを作成するためです。それは実際にいつ実行されますか?これはノードrequireステートメントに関連するより一般的な質問です。次のポイントを参照してください。
  • すべてのrequire文はいつ実行されますか? nodejsサーバーを起動するとどうなりますか?または私がAPIを呼び出すと?
+0

モンゴースモジュールを見てください。 – Yahya

+0

@Yahya私はそれについて研究していました。しかし、私は自分の文書にスキーマを強制したくありません。 – jerry

+0

[Monk](https://automattic.github.io/monk/)はどうですか? – Yahya

答えて

0

Promise.promisifyAllの使用は私には不愉快に思えますが、あなたの基本的な構造は多かれ少なかれ正しいです。私のための基本的な問題(それは本当に問題ではありません - あなたのコードはうまくいくように見えます)は、約束ベースのコールバックと非同期のコールバックを組み合わせたものです。私が言ったように、まだ動作するはずですが、私は可能な限り1つに固執したいと考えています。

モデルクラスは、あなたコード(とない他の誰かによって書かれたいくつかのライブラリ)である場合は、簡単に代わり、コールバックのためにそれを書いて、それをラップするPromise.promisifyAllを使用しての、直接の約束を使用するように書き換えることができます。

static getAllJobs() { 

    // connect to the Mongo server 
    return MongoClient.connectAsync(utils.getConnectionString()) 

     // ...then do something with the collection 
     .then((db) => { 
      // get the collection of jobs 
      const jobs = db.collection('jobs'); 

      // I'm not that familiar with Mongo - I'm going to assume that 
      // the call to `jobs.find().toArray()` is asynchronous and only 
      // available in the "callback flavored" form. 

      // returning a new Promise here (in the `then` block) allows you 
      // to add the results of the asynchronous call to the chain of 
      // `then` handlers. The promise will be resolved (or rejected) 
      // when the results of the `job().find().toArray()` method are 
      // known 
      return new Promise((resolve, reject) => { 
       jobs.find().toArray((err, jobs) => { 
        if(err) { 
         reject(err); 
        } 
        resolve(jobs); 
       }); 
      }); 
     }); 
} 

getAllJobsリターンを約束することができますチェーンthencatchハンドラへのこのバージョン:ここで

は私がgetAllJobs方法に近づくだろうかです。例:

JobModel.getAllJobs() 

    .then((jobs) => { 
     // this is the object passed into the `resolve` call in the callback 
     // above. Do something interesting with it, like 
     res.json(jobs); 
    }) 

    .catch((err) => { 
     // this is the error passed into the call to `reject` above 
    }); 

これは、上記のコードと非常によく似ています。唯一の違いは、私がPromise.promisifyAllの使用を省いたことです。あなた自身がコードを書いているのなら、&あなたは約束を使用したいと思っています。

重要な注意点:catchハンドラを含めることをお勧めします。そうしないと、エラーが飲み込まれて消えてしまい、コードが動作しない理由が不思議に思うことになります。あなたが必要と思わない場合でも、それをダンプするキャッチハンドラを書き込んでconsole.logにしてください。あなたがしてうれしいよ!

+0

私はこのhttp://softwareengineering.stackexchange.com/a/279003を読む前に、最初は同じことをやっていました。だから私はこのアプローチを使い終わった。また、各モジュールの上にあるrequireステートメントはいつ実行されるのか理解したいと思いますか?私の質問の最後の部分。 – jerry

+0

これで私に連絡してください。私はこの問題に立ち往生しています。 – jerry

+0

モジュールがロードされたときにインポートと要求が実行されることは、私自身の非公式の観察だけに基づいています。あなたのコメントに投稿したリンクについて:私はその議論を見ていない - それはパフォーマンスがそのアプローチを使用して良いことを示唆している。それは事実かもしれませんが、パフォーマンスが主な関心事であれば、それに行きましょう。私は通常、コードを書くことを念頭に置いています。コードをシンプルで読みやすく、必要がない限りパッケージを含めないようにしてください。 – Kryten