2016-07-21 60 views
-1

我有一個方法在我的控制器之一。控制器的目的是使用webshot package打印一組網址。如何改進Node.js和Express.js中的代碼,避免回調地獄

這是有問題的代碼:

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


    }); 
}); 

此代碼工作沒有問題......但我想做得更好。我不知道有多少網址需要檢查(這是重要的細節,因爲我需要爲每個或類似的做一個)。

我已閱讀約async package ...更好的選擇將此代碼移動到像async.parallel?我可以在代碼中使用yield嗎?

謝謝!

+0

我不知道爲什麼這個問題被否決...... – chemitaxis

回答

1

這是碼流的例子基於內部函數:

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

我比其他人更喜歡這種方式。 – chemitaxis

2

由於您使用Promise,我推薦Promise.all

它返回一個承諾,當迭代參數中的所有承諾都解決了,或拒絕了第一個傳遞的承諾拒絕的原因。

似乎它可以解決您的問題。

例子:

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

感謝您的代碼,看看很好;) – chemitaxis

0

說實話,你的代碼看起來不錯。

如果您不打算在此添加更多邏輯,請保持原樣。

什麼可以做得更好,正在遷移到ES6語法和提取anotherValue函數,但我不知道這是否適用於您的情況。

1

對於這樣一個簡單的例子,你不需要使用async。使用原生承諾:

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

感謝您的代碼;) – chemitaxis

+0

@chemitaxis更新代碼與小非關鍵修復;將此標記爲回覆。 –

+0

好吧,你知道我的問題爲什麼是投票下來? O_o – chemitaxis