簡體   English   中英

在承諾中包裝MongoDB調用

[英]Wrapping MongoDB calls within a Promise

我通常使用Meteor(1.0.3),但在一種特殊情況下,我使用的是原始服務器端路由來渲染文件-因此,我不在Meteor方法之外。

我也使用節點fs.writeFile / fs.readFile和exec命令調出Linux命令行實用程序。

我對此的唯一觀點是節點調用當然是異步的。 因此,我選擇使用節點Q庫來管理異步回調。

在我添加一行代碼以調用MongoDB數據庫之前,所有這些都有效。

像這樣的電話:

var record_name = Mongo_Collection_Name.findOne({_personId: userId}, {fields: {'_id': 0}});

產生以下錯誤:

[錯誤:沒有光纖就等不及了]

僅當我將函數包裝在Promise中時,才會發生錯誤。

例如,類似這樣的東西會拋出:

getRecordExample = function () {
  var deferred = Q.defer();
  var record_name = Mongo_Collection_Name.findOne({_personId: userId}, {fields: {'_id': 0}});

  // do something

  // if no error
  deferred.resolve(record_name);

  return deferred.promise;
}

如果我使用流星纖維庫,則不會出現以下錯誤:

getRecordExample = function () {
  var deferred = Q.defer();
  Fiber = Npm.require('fibers');
  var record_name

  Fiber(function () {
    record_name = Mongo_Collection_Name.findOne({_personId: userId});
  }).run()
  // do something

  // if no error
  deferred.resolve(record_name);

  return deferred.promise;
}

但是,record_name變量在光纖外部是未定義的,所以據我所知,我沒有辦法將變量傳遞到Fiber范圍之外。

更精確的例子

這有點長,所以您必須向下滾動才能看到全部內容。 我基本上是在這里構建工作流,所以有流程和子流程。

// both/routes.js
Router.route('/get-route', function(req, res) {
  // get the userId then start the workflow below

  // using Promises here because these were firing concurrently
  Q(userId)
  .then(process_1)
  .then(process_2)
  .done();
}, { name: 'server-side-ir-route', where: 'server' }

// server.js
process_1 = function (userId) {
  sub_process_1(userId);

  sub_process_2(userId);

  return userId;
}

process_2 = function (userId) {
  sub_process_3(userId);

  sub_process_4(userId);

  return userId;
}

sub_process_1 = function (userId) {
  var result = get_record_1(userId);

  // do stuff with result

  // using Q library to call out to async fs.writeFile, return Promise
  fs_writeFile_promise(result)
  .catch(function (error) {
    console.log('error in sub_process_1_write', error);
  })
  .done(function () {
    console.log('done with sub_process_1');
  }

  return userId;
}.future() // <-- if no future() here, the exception is thrown.

sub_process_2 = function (userId) {
  var result = get_record_2(userId);

  // do stuff with result

  // using Q library to call out to async fs.writeFile, return Promise
  fs_writeFile_promise(result)
  .catch(function (error) {
    console.log('error in sub_process_1_write', error);
  })
  .done(function () {
    console.log('done with sub_process_1');
  }

  return userId;
}.future()

// async because of I/O operation (I think)
get_record_1 = function (userId) {
  var record_1 = Mongo_Collection_Name.findOne({'userId': userId});
  // do stuff
  return record_1;
}
get_record_2 = function (userId) {
  var record_2 = Mongo_Collection_Name.findOne({'userId': userId});
  // do stuff
  return record_2;
}

// async operation using Q library to return a Promise
fs_writeFile_promise = function (obj) {
  var deferred = Q.defer();
  fs.writeFile(obj.file, obj.datas, function (err, result) {
    if (err) deferred.reject(err);
    else deferred.resolve('write data completed');
  });
  return deferred.promise;
}

現在,讓我們假設process_2函數與process_1完全一樣

另外,我們應該假設每個函數中都有console.log('step_start')和console.log('step_end')。 這是在命令行中的樣子:

  • 開始過程
  • 最終過程
  • 開始過程1
  • 最終過程1
  • 啟動過程2
  • 開始子流程1
  • 得到記錄1
  • 開始子流程2
  • 獲得記錄2
  • 返回記錄1
  • 結束子流程1
  • 在子流程1中稱為writeData
  • 返回記錄2
  • 在子流程2中稱為writeData
  • 最終過程2
  • 結束子流程1

我必須在sub_process_1()函數上放置一個Fiber(期貨)的原因是因為當我將函數process_1()放在頂部的Q鏈中時,出現了錯誤:無法等待沒有光纖]。

如果我從頂部的Q鏈中刪除了process_1(),並從sub_process_1()中刪除了.future(),則不會引發異常。

問題

  • 為什么調出Promise中的Mongo集合會導致Meteor應用程序中出現光纖錯誤?
  • 通常,在同步功能內調用異步功能是否會導致同步功能變為異步功能?
  • 我該如何解決這個問題?

解決此問題的最常見方法是將使用Meteor函數的異步回調包裝在Meteor.bindEnvironment()

如果您使用Meteor核心WebApp包來處理服務器端路由,則代碼將如下所示(也在meteorpad中 ):

WebApp.connectHandlers.use(
  '/test',
  Meteor.bindEnvironment(function(req, res, next) {
    var someSyncData = Players.findOne();
    res.write(JSON.stringify(someSyncData));
    res.end();
  })
);

除非您要使多個異步事件同時運行,否則不需要使用光纖或諾言。

為了處理文件讀取或尚未同步的其他功能,Meteor還提供了Meteor.wrapAsync()使它們同步。

也有軟件包和幫助頁面 ,可為您提供其他高級選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM