2016-07-21 14 views
-1

Ich habe eine Methode in einem meiner Controller. Der Zweck des Controllers ist das Drucken eines Arrays von URLs unter Verwendung von webshot package.Wie verbessert man diesen Code in Node.js und Express.js Callback-Hölle zu vermeiden

Dies ist der Code in Frage:

router.post('/capture', function (req, res, next) { 

    //Check params remove 

    var json = JSON.parse(req.body.data); 

    var promise = new Promise(function (resolve, reject) { 

    var totalImages = Object.keys(json).length; 
    var arrayListUrlImages = new Array(totalImages); 
    var counter = 0;   
    var completeDir = dir + ''; //Directory URL  

    for (var value of json) {  
     var url = 'http://example.com/' + id + '/' + value.anotherValue; 
     var folder = completeDir + id + '/' + value.anotherValue + '.jpg'; 

     //Options for capturing image 
     var options = { 
     renderDelay: 1000, 
     quality: 100, 
     phantomConfig: 
     { 
      'local-to-remote-url-access': 'true', 
      'ignore-ssl-errors': 'true' 
     }  
     }; 

     var anotherValue = value.anotherValue; 

     (function (anotherValue) { 

      webshot(url, folder, options, function (err) { 
     // screenshot now saved    

     if (err === null) { 

      var urlImage = "http://example.com/images/" + id + "/" + anotherValue + ".jpg"; 
      arrayListUrlImages.push(urlImage); 
      counter++; 
      console.log("Counter: " + counter); 

      if (counter === totalImages) {     
      resolve(arrayListUrlImages); 
      } 
     } 
     else { 
      reject(err); 
     } 
     });  
     })(anotherValue); 


    } 




    }).then(function (arrayImages) { 

    res.send(arrayImages); 


    }).catch(function (errorVale) { 
    res.send(null); 


    }); 
}); 

Dieser Code wird ohne Probleme arbeiten ... aber ich würde besser tun. Ich weiß nicht, wie viele URLs überprüft werden müssen (Dies ist ein wichtiges Detail, weil ich für jedes oder ähnliche eine machen muss).

Ich habe über async package gelesen ... Ist bessere Option diesen Code zu etwas wie async.parallel verschieben? Kann ich den Ertrag in meinem Code verwenden?

Danke!

+0

Ich weiß nicht, warum diese Frage überstimmt wird ... – chemitaxis

Antwort

1

Dies ist ein Beispiel von Codefluss basiert auf inneren Funktionen:

router.post('/capture', function (req, res, next) { 
    // Definitions 

    // Load image 
    function loadImage(value) { 
     var url = 'http://example.com/' + id + '/' + value.anotherValue; 
     var folder = completeDir + id + '/' + value.anotherValue + '.jpg'; 

     //Options for capturing image 
     var options = { 
      renderDelay: 1000, 
      quality: 100, 
      phantomConfig: 
      { 
       'local-to-remote-url-access': 'true', 
       'ignore-ssl-errors': 'true' 
      }  
     }; 

     return webshotPromise(url, folder, options); 
    } 

    // Load whebshot as a promise 
    function webshotPromise(url, folder, options) { 
     return new Promise((resolve, reject) => { 
      webshot(url, folder, options, function (err) { 
       if (err) { 
        reject(err); 
       } 

       var urlImage = "http://example.com/images/" + id + "/" + anotherValue + ".jpg"; 
       resolve(urlImage); 
      } 
     }); 
    } 

    // The method flow 
    const json = JSON.parse(req.body.data); 

    // Get json keys and iterate over it to load 
    Promise.all(
     Object.getOwnPropertyNames(json).map(key => loadImage(json[key])) 
    ) 
    // Got list of urls 
    .then((list) => { 
     res.json(list); 
    }, (error) => { 
     console.error(error); 
     res.json(null); 
    }); 
}); 
+0

Ich mag diesen Weg mehr als den anderen. – chemitaxis

2

Da Sie Promise verwenden, empfehle ich Promise.all.

Es gibt eine Zusage zurück, die sich löst, wenn alle Versprechen im iterablen Argument aufgelöst wurden, oder mit dem Grund der ersten abgelehnten Zusage zurückgewiesen wird.

Scheint wie es Ihr Problem löst.

Beispiel:

downloadOne = url => new Promise(resolve => { 
    webshot(url, ....., (err, res) => resolve(res)); 
}) 

router.post('/capture', function (req, res, next) { 
    var urls = JSON.parse(req.body.data); 
    Promise.all(urls.map(downloadOne)).then(req.send); 
} 
+0

Danke für den Code, schauen gut;) – chemitaxis

0

Ehrlich gesagt, sieht der Code in Ordnung.

Wenn Sie hier nicht mehr Logik hinzufügen, lassen Sie es so wie es ist.

Was kann besser gemacht werden, migriert es auf ES6-Syntax und Extrahieren einer anderenWert-Funktion, aber mir ist nicht bekannt, ob dies für Ihren Fall gilt.

1

Sie müssen async für solch ein einfaches Beispiel nicht verwenden. Verwendung nativer Versprechen:

router.post('/capture', function (req, res, next) { 

    //Check params remove 

    const json = JSON.parse(req.body.data); 

    Promise.all(Object.getOwnPropertyNames(json).map((key) => { 
     var value = json[key]; 

     var url = 'http://example.com/' + id + '/' + value.anotherValue; 
     var folder = completeDir + id + '/' + value.anotherValue + '.jpg'; 

     //Options for capturing image 
     var options = { 
      renderDelay: 1000, 
      quality: 100, 
      phantomConfig: 
      { 
       'local-to-remote-url-access': 'true', 
       'ignore-ssl-errors': 'true' 
      }  
     }; 

     return new Promise((resolve, reject) => { 
      webshot(url, folder, options, function (err) { 
       if (err) { 
        reject(err); 
        return; 
       } 

       var urlImage = "http://example.com/images/" + id + "/" + anotherValue + ".jpg"; 
       resolve(urlImage); 
      } 
     }); 
    })) 
    .then((listOfUrls) => { 
     res.json(listOfUrls); // List of URLs 
    }, (error) => { 
     console.error(error); 
     res.json(null); 
    }); 
}); 
+0

Danke für den Code;) – chemitaxis

+0

@chemitaxis Update-Code mit kleinen nicht kritischen Fix; Markieren Sie dies als eine Antwort so. –

+0

Ok, weißt du, warum meine Frage nach unten geht? O_o – chemitaxis