2017-01-06 13 views
0

我是nodejs/expressjs和mongodb的新手。我正在嘗試創建一個將數據公開給我的移動應用程序的API,我嘗試使用Ionic框架構建它。如何將承諾返回給NodeJS/ExpressJS中的路由器回調

我有一個路線設置這樣

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

我在我的模型的函數,從MongoDB中讀取數據。我正在使用藍鳥承諾庫來轉換我的模型函數以返回承諾。

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

我在模型

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語句相關的更一般的問題。見下一點。
  • 何時需要運行語句?當我啓動nodejs服務器?或者當我打電話給api?
+0

看看貓鼬模塊。 – Yahya

+0

@Yahya我研究過它。但我不想在我的文檔上執行模式。 – jerry

+0

[Monk](https://automattic.github.io/monk/)呢? – Yahya

回答

0

您的基本結構或多或少是正確的,儘管您對我使用Promise.promisifyAll似乎很尷尬。對我來說基本問題(這不是一個真正的問題 - 你的代碼看起來像是可以工作的)是你正在混合和匹配基於承諾和基於回調的異步代碼。正如我所說,它應該仍然有效,但我寧願儘可能地堅持一個。

如果你的模型類是代碼(而不是一些庫別人寫的),你可以很容易地把它改寫直接使用,而不是寫它的回調,然後使用Promise.promisifyAll來包裝它的承諾。

這是我怎麼會接近getAllJobs方法:

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處理程序。例如:

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處理程序。如果你不這樣做,那麼你的錯誤將被吞噬並消失,你會想知道爲什麼你的代碼不工作。即使你不認爲你需要它,也可以編寫一個catch處理程序將其轉儲到console.log。你會很高興你做到了!

+0

我在閱讀這個http://softwareengineering.stackexchange.com/a/279003之前最初做了同樣的事情。所以我最終使用了這種方法。我還想了解每個模塊頂部的require語句何時運行?我的問題的最後一部分。 – jerry

+0

你可以請回到我這個嗎?我被困在這個問題上。 – jerry

+0

這是我的理解(完全基於我自己的非正式觀察 - 我從來沒有測試過)導入和需求是在模塊加載時執行的。關於您在評論中發佈的鏈接:我沒有看到這種討論 - 它表明使用這種方法的表現更好。這可能是事實,如果表現是你最關心的問題,那就去做吧。我通常會在編寫代碼時考慮一些其他問題:保持代碼簡單易讀,避免包含軟件包,除非需要。 – Kryten