Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/461.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何改进Node.js和Express.js中的代码以避免回调地狱_Javascript_Node.js_Express_Yield - Fatal编程技术网

Javascript 如何改进Node.js和Express.js中的代码以避免回调地狱

Javascript 如何改进Node.js和Express.js中的代码以避免回调地狱,javascript,node.js,express,yield,Javascript,Node.js,Express,Yield,我的一个控制器中有一个方法。控制器的用途是使用打印URL数组 以下是相关代码: 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.key

我的一个控制器中有一个方法。控制器的用途是使用打印URL数组

以下是相关代码:

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,这是一个重要的细节,因为我需要对每个URL或类似URL进行检查

我读过关于。。。更好的选择是将此代码移动到类似async.parallel的位置吗?我可以在代码中使用yield吗


谢谢

既然您使用的是Promise,我推荐您

它返回一个承诺,当iterable参数中的所有承诺都已解决,或由于第一个通过的承诺拒绝而拒绝时,该承诺将解决

看起来它解决了你的问题

例如:

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

老实说,你的代码看起来不错

如果您不打算在这里添加更多逻辑,请保持原样

可以做得更好的是将其迁移到ES6语法并提取另一个值函数,但我不知道这是否适用于您的情况。

对于这样简单的示例,您不需要使用异步。使用本地承诺:

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

这是一个基于内部函数的代码流示例:

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

@chemitaxis更新代码,具有小的非关键修复;我不知道为什么它不够抽象。我更喜欢这种方式。我不知道为什么这个问题被否决了。。。