Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Robson Kerner

Valor de variável em diferentes escopos.

Recommended Posts

Boa noite senhores.

 

Estou tendo problemas ao implementar uma funcionalidade em javascript e gostaria de contar com a colaboração de vocês.

 

Estou trabalhando em um ambiente rest com nodejs e ao implementar um teste na qual consiste:

1) buscar dados de um banco mysql,

2) com a informação eu faço uma segunda busca em um banco mongodb.

 

O problema está na variavel (feed) que carrega toda essa informação para retorno em formato json. Ela simplesmente retorna vazia. Já lí varios artigos sobre variáveis, declaração e escopo, mas meu problema ainda continua.

var feed = [];

module.exports = router.route('/user-feeds/:id')
  .get(function(req,res){
    
    sql = 'consulta_sql';

    mysql_conn.query(sql, function(err, row) {

      if (err) console.log(err);

        row.forEach( function(f){
          feed[f.pathXml] = {'idCategoryInfo': f.idCategoryInfo, 
                             'idFeeds': f.id, 
                             'parhXml': f.pathXml, 
                             'items': []};

          mFeed.find({'idFeeds': f.id}, function(err, news){

            if (err) console.log(err);
            
            news.forEach( function(n){
              feed[n.pathXml]['items'].push({ 'image': n.image, 
                                              'title': n.title, 
                                              'author': n.author, 
                                              'link': n.link, 
                                              'content': n.content, 
                                              'published': n.published });
            });
          });      
        });
      });
      res.setHeader('content-type', 'application/json');
      res.json(feed);		
    });

detalhe: ao utilizar do comando console.log() eu consigo visualizar durante o script todo o conteudo da variavel, e somente quando vou envia-la atraves do res.json que ela está vazia.

 

Obrigado e boa noite a todos.

Compartilhar este post


Link para o post
Compartilhar em outros sites

o res.json() precisa ficar dentro do callback do .find()

mFeed.find({'idFeeds': f.id}, function(err, news){
fora dele, como o node é assincrono, a variavel feed não tem valor.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom dia W.B. tudo bem?

 

Já havia feito um teste e realmente ele tras! No entanto vem um erro também quando o meu retorno do mysql tras mais de um canal de feeds que o usuários assina. Ao executar mais de uma vez o mFeed(...) para trazer as noticias das assinaturas.

 

Se deixo o res.json(...) dentro neste momento eu tenho um retorno de erro com o header

/var/www/myapp/node_modules/mongoose/lib/utils.js:419
        throw err;
              ^
Error: Can't set headers after they are sent.
    at ServerResponse.OutgoingMessage.setHeader (http.js:690:11) 

Alem de que tenho outro foreach dentro do mFeed para inserir as noticias na variavel.

 

-> no banco mysql consigo as assinaturas dos feeds dos usuarios

-> para cada assinatura eu vou no mongodb e busco as noticias

 

-> a ideia de retorno para o usuário seria mais ou menos esta:

[{
    pathXml: 'feeds assinado',
    items: [{'noticia'},
            {'noticia'},
            ...]
},
{
    pathXml: 'feeds assinado',
    items: [{'noticia'},
            {'noticia'},
            ...]
},
{...}]

Alguma sugestão.. talvez mudar um pouco a lógica? Abraços.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Hum.. entendi.

 

Então para cada linha retornada no mysql, vc faz uma query no mongo.

Cara, isso em performance é um inferno.. evita esse tipo de consulta em loop.

 

Troca:

mFeed.find({'idFeeds': f.id}
por:

mFeed.find({'idFeeds': { $in: [1,2,3,4,5,] }
entendeu a idéia ?

uma única query no mongo, a partir do array retornado do mysql.

 

O seu primeiro loop do mysql, vai só fazer esse array pro mongo ir uma única vez.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ok, ok vou fazer as alterações e já posto os resultado aqui.

 

 

Quanto a discussão acima embora não seja viavél, é possível de ser realizada? De se carregar o valor da variavel pra fora do contexto?

 

Abraços.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não, e nesse caso o motivo é que é assincrono.

 

Não é só um problema de contexto, mas sim de "time"

Compartilhar este post


Link para o post
Compartilhar em outros sites

Boa noite!

 

Segue as alterações que fiz no código:

module.exports = router.route('/user-feeds/:id')
  .get(function(req,res){
    sql = 'query_tras_todos_os_feeds_assinados';

    mysql_conn.query(sql, function(err, row) {

      if (err) console.log(err);
      row.forEach( function(f){
        assign.push(f.id);
      });

      mFeed.find({'idFeeds': {$in: assign}}, function(err, news){
        if (err) console.log(err);
        res.setHeader('content-type', 'application/json');
	res.json(news);						  			
      });
    });		
  });

Bom assim está OK e retornando as notícias.

O json está assim:

[{
   'pathXml': feed assinado,
   'title': title,
   'content': content,
   ...
},
{
   'pathXml': feed assinado2,
   'title': title2,
   'content': content2,
   ...
},
{
'pathXml': feed assinado1 novamente,
'title': title3,
'content': content3,
...
},
{...3}]

Eu removi o foreach na variavel news.

 

Gostaria agora de abrir a discussão de como posso fazer a organização e se é viavél para o json ficar assim:

[{
    pathXml: 'feeds assinado',
    items: [{'titulo1', 'content1'},
            {'titulo2', 'content2'},
            ...]
},
{
    pathXml: 'feeds assinado2',
    items: [{'titulo3', 'content3'},
            {'titulo4', 'content4'},
            ...]
},
{...}]

O objetivo disso é para manter o front-end (outro projeto em angularJs) sem a necessidade de refatoração pois já existe uma função que retorna o json desta maneira em uma api rest com php.

 

Obrigado. Abraços.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.