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

我知道在Nodejs / Express中链接承诺的最好方法是:

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

但最近不得不使用async和q模块迭代列表/数组并运行异步函数.我想知道有更好的方式来做/写这个 –

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});
    });

如果我做错了,请纠正我.功能明智的代码运行正常但我认为我可以以某种方式重构它以更好地查看和阅读.

谢谢.

最佳答案 您的代码可以更清晰,更短.

基本的想法是

>将回调转为承诺,例如,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});
  })
点赞