2016-07-21 6 views
-1

私のコントローラの1つにメソッドがあります。コントローラの目的は、webshot packageを使用してURLの配列を出力することです。Node.jsとExpress.jsでこのコードを改善する方法コールバックhellを避ける

これは、問題のコードです:

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


    }); 
}); 

このコードは問題なく働いている...しかし、私はもっとうまくしたいと思います。どのくらい多くのURLをチェックする必要があるのか​​わかりません(これは重要な詳細なので、それぞれまたは同等のために行う必要があります)。

私は約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.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

関連する問題