异步循环中的异步循环:一个好主意?

时间:2018-05-24 20:48:17

标签: javascript node.js

我有一些javascript代码执行以下操作:

  1. 读取.txt文件并填写对象数组
  2. 循环通过这些itens
  3. 遍历每个itens中的一系列链接,并使用nightmarejs
  4. 发出请求
  5. 将结果写入Sql Server
  6. 我的代码是这样的:

        const Nightmare = require('nightmare');
        const fs = require('fs');
        const async = require('async');
        const sql = require('mssql');
    
        var links = recuperarLinks();
    
        function recuperarLinks(){
        //Read the txt file and return an array
        }
    
        const bigFunction = () => {     
            var aparelho = '';  
            async.eachSeries(links, async function (link) {
                console.log('Zip Code: ' + link.zipCode);
                async.eachSeries(link.links, async function(url){
                    console.log('URL: ' + url);
                    try {
                        await nightmare.goto(link2)
                            .evaluate(function () {
                                //return some elements
                            })
                            .end()
                            .then(function (result) {
                                //ajust the result
                                dadosAjustados.forEach(function (obj) {
                                    //save the data 
                                    saveDatabase(obj, link.cep);                           
                                });             
                            });
                    } catch (e) {
                        console.error(e);
                    }
                }
                }, function(err){
                    console.log('Erro: ');
                    console.log(err);
                })        
            }, function (erro) {
                if (erro) {
                    console.log('Erro: ');
                    console.log(erro);
                }
            });
        }
    
    async function salvarBanco(dados, cep){
        const pool = new sql.ConnectionPool({
          user: 'sa',
          password: 'xxx',
          server: 'xxx',  
          database: 'xxx'
        });
        pool.connect().then(function(){
            const request = new sql.Request(pool);
            const insert = "some insert"
            request.query(insert).then(function(recordset){
                console.log('Dado inserido');           
                pool.close();
            }).catch(function(err){
                console.log(err);
                pool.close();
            })
        }).catch(function(err){
            console.log(err);
        });        
    }
    
    lerArquivo();
    

    它工作正常,但我发现这个异步循环在另一个异步循环中,就像某种黑客一样。

    我的输出是这样的:

    Fetching Data from cep 1
    Fetching Data from url 1
    Fetching Data from cep 2
    Fetching Data from url 2
    Fetching Data from cep 3
    Fetching Data from url 3
    

    然后它开始发出请求。这样做有更好的(也可能是正确的方法)吗?

1 个答案:

答案 0 :(得分:0)

如果您要将您的呼叫序列化为nightmare.goto(),并且希望简化代码,而这似乎是您尝试使用await,那么您可以避免混合基于回调的异步承诺的图书馆,只使用这样的承诺来实现你的目标:

async function bigFunction() {     
    var aparelho = '';  
    for (let link of links) {
        for (let url of link.links) {
            try {
                let result = await nightmare.goto(url).evaluate(function () {
                        //return some elements
                }).end();
                //ajust the result
                await Promise.all(dadosAjustados.map(obj => saveDatabase(obj, link.cep)));
            } catch (e) {
                // log error and continue processing
                console.error(e);
            }
        }
    }
}
  

异步循环中的异步循环:一个好主意?

对于涉及异步操作的嵌套循环,它有时非常精细且必要。但是,必须仔细设计循环,以便适当地工作并且是干净,可读和可维护的代码。您的bigFunction()似乎不是我的混合异步编码样式。

  

它工作正常,但我在另一个异步循环中找到了这个异步循环,就像某种黑客一样。

如果我正在教一个初级程序员或对来自任何级别的开发人员的代码进行代码审查,我绝不会允许混合promises的代码和基于回调的异步库。它只是混合了两种完全不同的编程风格,用于控制流程和错误处理,所有你得到的是一个非常难以理解的混乱。选择一个型号或另一个。不要混在一起。就个人而言,在我看来,该语言的未来是异步控制流和错误传播的Promise,因此我会使用它。

注意:这似乎是伪代码,因为此代码中使用的某些引用未使用或定义,例如resultdadosAjustados。因此,您必须将此概念适应您的真实代码。对于未来,我们可以为您提供更完整的答案,并且通常会提供您甚至不知道的建议改进,如果您包含真实代码,而不是缩写伪代码。