2016-07-06 13 views
4

Ich weiß, dass beste Weg, um Kette Versprechen in NodeJS/Express ist wie:Best Practice für Versprechen in NodeJS/Express Verkettungs

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

Aber vor kurzem von der Asynchron-und q-Modul zu verwenden hatte eine Liste iterieren/Array und führen Sie eine asynchrone Funktion aus. Ich wollte wissen, dass gibt es bessere Möglichkeit, dies zu tun/Schreiben -

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

Bitte korrigiert mich, wenn ich etwas falsch tue. Funktionalität weise der Code läuft richtig, aber ich denke, ich kann es irgendwie umgestalten, um besser zu schauen und zu lesen.

Danke.

+0

Die Verwendung von 'async.js' zusammen mit Versprechen ist hier die wichtigste gute Praxis. – Bergi

+0

@AlongkornChetasumon Sie können nicht einfach das Tag [tag: Bluebird] zur Frage hinzufügen, wenn das OP diese Bibliothek nicht verwendet! – Bergi

+0

Werfen Sie einen Blick auf die [latent antipattern] (http://stackoverflow.com/q/23803743/1048572) und wie man es vermeidet. – Bergi

Antwort

2

Ihr Code kann sauberer und kürzer sein.

Grundideen sind

  • wiederum Rückruf, zB promisify() von bluebird.js tun kann versprechen, dass
  • async.each Teil refactor sein kann Promise.all Versprechen zu nennen parallel
  • neu ordnen .then Kette
  • javascript es6 ist sauberer als ältere Version

Probe Refactoring Version

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

Wenn Sie bitte die umgestaltete Version veröffentlichen könnten. Es würde mir mehr Klarheit darüber geben, wie ich vorgehen und besser verstehen kann. Sie können die nitty gritty überspringen und nur das Skelett des refaktorierten Codes wird ausreichen. Vielen Dank. –

+0

@SiddharthSrivastva, siehe Beispiel oben, ich habe meinen Beitrag aktualisiert –