在Nodejs / Express中链接承诺的最佳实践

我知道在Nodejs / Express中链接promise的最佳方式是:

doSomeThing() .then() .then() .catch(); 

但最近不得不使用async和q模块遍历列表/数组并运行asynchronous函数。 我想知道是否有更好的方式来做/写这个 –

 var deferred = Q.defer(); var deferred2 = Q.defer(); models.Local.findOne({ where: { id: parseInt(req.body.localid) } }) .then(function(resultLocal){ if(!resultLocal){ return res.status(404).json( { "status" : "error", 'error': "Local Not Found" }); } return models.Documents.create(req.body.document); }) .then(function(docCreated){ var attributes = req.body.document.Attributes; async.each(attributes, function(item, callback) { models.Doc_Tags.create({ value: item.value, attribute_id: item.id, document_id: docCreated.id }) .then(function(attributeCreated){ var upObj = {}; upObj[item.col_name] = item.value; models[item.table_name].update(upObj,{ where:{ id: req.body.document.local_id } }) .then(function(primaryUpdated){ deferred2.resolve(); }) .catch(function(error){ return res.status(400).json({status: 'error', error:error.message}); }); deferred2.promise .then(function(){ callback(); }) .catch(function(error){ return res.status(400).json({status: "error", error: error.message}); }); }) .catch(function(error){ return res.status(400).json({status: 'error', error:error.message}); }); }, function(err,r){ if( err ) { return res.status(400).json({status: 'error', error:err.message}); } else { console.log('All attributes Associated'); deferred.resolve(docCreated); } }); deferred.promise.then(function(result, attributes){ var obj = req.body.Local; models.Local.update(obj, { where: { id: result.local_id } }) .then(function(resultUpdate){ return res.status(201).json({status: "success", document: result}); }) .catch(function(error){ return res.status(400).json({status: "error", error: error.message}); }); }) .catch(function(error){ return res.status(400).json({status: "error", error: error.message}); }); }) .catch(function(error){ return res.status(400).json({status: "error", error: error.message}); }); 

请纠正我,如果我做错了什么。 function明智的代码运行正常,但我认为我可以重构它以外观和阅读更好。

谢谢。

你的代码可以更干净,更短。

基本的想法是

  • 转回来承诺,例如,bluebird.js的promisify()可以做到这一点
  • async.each部分可以重构为Promise.all并行调用promise
  • 重新安排,然后连锁
  • JavaScript ES6比旧版本更清洁

样本重构版本

 const Promise = require('bluebird') // CustomError should be separated to another node module class CustomError { constructor(message, code) { this.code = code this.message = message } } let docCreated = undefined function getPromiseParams(item) { return Promise.try(() => { return models.Doc_Tags.create({ value: item.value, attribute_id: item.id, document_id: docCreated.id }) }).then(attributeCreated => { const upObj = {}; upObj[item.col_name] = item.value; return models[item.table_name].update(upObj, { where:{ id: req.body.document.local_id } }) }).then(primaryUpdated => { return docCreated }).catch(error => { throw new CustomError(error.message, 400) }) } Promise.try(() => { return models.Local.findOne({ where: { id: parseInt(req.body.localid) } }) }).then(resultLocal => { if(!resultLocal) throw new CustomError('Local Not Found', 404) return models.Documents.create(req.body.document) }).then(_docCreated => { docCreated = _docCreated // assign value to docCreated const attributes = req.body.document.Attributes const promiseParams = attributes.map(item => getPromiseParams(item)) return Promise.all(promiseParams) }).then(() => { const obj = req.body.Local return models.Local.update(obj, { where: { id: result.local_id }}) }).then(() => { return res.status(201).json({status: "success", document: docCreated}) }).catch(error => { return res.status(error.code || 400).json({status: "error", error: error.message}); })