Jump to content
Luciano Silveira Marco

Retorno assincrono encadeando promessas

Recommended Posts

Pessoal, boa noite!

 

Gostaria de ver a possibilidade de implementar o "Encadeando promessas" neste código, de modo em que eu possa atribuir o retorno da funcão CalculaDistancia para alguma variável, o "xtalk" é o valor que eu preciso, mas só consigo utilizar dentro da função, preciso deste valor atribuído:

var xvar = CalculaDistancia(xxxxxx,xxxxxx);

O resultado desta função já vem de um encadeamento que consegui fazer rodar olhando exemplos, só que agora preciso subir mais um nível conforme descrevi.

Agradeço quem puder ajudar ou tiver alguma idéia.

function testadistancia() {          
          CalculaDistancia(mapcord[0].varlat+','+mapcord[0].varlon,mapcord[1].varlat+','+mapcord[1].varlon)
          .done(function(response){
                var origins = response.originAddresses;
                for (var i = 0; i < origins.length; i++) {
                     var results = response.rows[i].elements;
                     for (var j = 0; j < results.length; j++) { 
                          var xtroca = substituiVirgula(results[j].distance.text);
                          xtalk=parseFloat(xtroca);
                          alert(xtalk);
                      }
                }
          })         
        }

Share this post


Link to post
Share on other sites

você nunca vai ser capaz de fazer isso:

var xvar = CalculaDistancia(xxxxxx,xxxxxx);
porque é algo assincrono.

Encadear promessas vai melhorar a legibilidade do código, mas não vai te dar a possibilidade de atribuir, porque é assíncrono.

Share this post


Link to post
Share on other sites

Você não precisa realmente atribuir. Você pode sim trabalhar com um sistema assíncrono sem isso.

 

Faça um callback:

 

function testadistancia(callback) {
  CalculaDistancia(mapcord[0].varlat+','+mapcord[0].varlon,mapcord[1].varlat+','+mapcord[1].varlon)
  .done(function(response){
        var origins = response.originAddresses;
        for (var i = 0; i < origins.length; i++) {
             var results = response.rows[i].elements;
             for (var j = 0; j < results.length; j++) {
                  var xtroca = substituiVirgula(results[j].distance.text);
                  xtalk=parseFloat(xtroca);
                  callback(null, xtalk);
              }
        }
  })
}
ai você usa:

 testadistancia(function(err, xtalk){
   alert(xtalk);
});
Note que deixei o primeiro argumento como err, porque esse é um padrão bem aceito na comunidade.

 

Agora você só precisa ver se é realmente isso, porque está dentro de 2 loops ali.

O resultado esperado deveria ser o que? um array?

Share this post


Link to post
Share on other sites

 

 

Bruno, estou tentando fazer a implementação conforme seu código, e como eu não expliquei o formato em que está o array que preciso organizar, no final do exemplo do seu código eu acredito que está modificando os valores de origem da array e não a ordem:

o array de coordenada que tenho é mapcord{('varlat': xxxxxxx, 'varlon':xxxxx)}

esse array é preenchido aleatoriamente por coordenadas de endereços, logo preciso otimizar esta rota, então utilizo uma função que que retorna a distancia entre duas coordenadas partindo sempre da posição 0, então a idéia é manter o modelo do array mas trocar as posições conforme proximidade preservando somente a posição 0 que é base.

 

Aqui está o modelo que você sugeriu e tentei implementar, mas aparece um erro informando que a propriedade 'varlat' não existe, porque acredito que ela está sendo mudada no processo, confere?

function reoganizaproximos() {
      for(var i = 0; i < mapcord.length - 1; i++){
      var disMinima=[];
      disMinima.push({'index':0, 'distancia':0});
      for(var f = i + 1; f < mapcord.length; f++){
      testadistancia(function(err, xtalk, i, f){
		var distancia = xtalk;

		if(distancia < disMinima.distancia){
			disMinima.index = f;
			disMinima.distancia = distancia;
		}
	   });	
	 }

	 if(disMinima.index !== i + 1){

		var mapcordTemp = mapcord[i + 1];

		mapcord[i + 1] = mapcord[disMinima.index];
		mapcord[disMinima.index] = mapcordTemp;
	 }
      }
      
     }

Share this post


Link to post
Share on other sites

Putz... não cara.. isso tá muito complicado.

Veja, como é um array, deveríamos chamar o callback uma única vez, fora do loop:

 

function testadistancia(callback) {
  CalculaDistancia(mapcord[0].varlat+','+mapcord[0].varlon,mapcord[1].varlat+','+mapcord[1].varlon)
  .done(function(response){
        var origins = response.originAddresses;
        var talks = [];
        for (var i = 0; i < origins.length; i++) {
             var results = response.rows[i].elements;
             for (var j = 0; j < results.length; j++) {
                  var xtroca = substituiVirgula(results[j].distance.text);
                  xtalks.push(parseFloat(xtroca));

              }
        }
        callback(null, xtalks);//chamar aqui
  })
}
entende?

 

Assim no retorno do callback você tem um array, e ele será chamado uma única vez, quando terminar todo o loop.

 

Eu ainda estou um pouco perdido com o que isso faz e como faz, mas analisando só o fluxo, isso aqui:

 

 if(disMinima.index !== i + 1){
está fora de onde deveria, porque essa variável só existe dentro do callback lá em cima.

 

 

Além disso, outro loop? putz.. acho que você não precisa desse outro.

 

Tem alguma chance de escrevermos cenários de testes para o que você quer fazer?

E dai sim, implementarmos ?

Share this post


Link to post
Share on other sites

Putz... não cara.. isso tá muito complicado.

Veja, como é um array, deveríamos chamar o callback uma única vez, fora do loop:

 

function testadistancia(callback) {
  CalculaDistancia(mapcord[0].varlat+','+mapcord[0].varlon,mapcord[1].varlat+','+mapcord[1].varlon)
  .done(function(response){
        var origins = response.originAddresses;
        var talks = [];
        for (var i = 0; i < origins.length; i++) {
             var results = response.rows[i].elements;
             for (var j = 0; j < results.length; j++) {
                  var xtroca = substituiVirgula(results[j].distance.text);
                  xtalks.push(parseFloat(xtroca));

              }
        }
        callback(null, xtalks);//chamar aqui
  })
}
entende?

 

Assim no retorno do callback você tem um array, e ele será chamado uma única vez, quando terminar todo o loop.

 

Eu ainda estou um pouco perdido com o que isso faz e como faz, mas analisando só o fluxo, isso aqui:

 

 if(disMinima.index !== i + 1){
está fora de onde deveria, porque essa variável só existe dentro do callback lá em cima.

 

 

Além disso, outro loop? putz.. acho que você não precisa desse outro.

 

Tem alguma chance de escrevermos cenários de testes para o que você quer fazer?

E dai sim, implementarmos ?

 

Claro, deixa eu tentar explicar ver se consigo sintetizar:

 

Conforme mencionei tenho um entrada de endereços que são transformados em coordenadas e inseridas num array chamado "mapcord{(varlat:xxxxx, varlon:xxxx)}" e tenho uma função chamada "testadistancia" que me devolve um valor float de distancia quando informo duas coordenadas.

Então o que eu preciso é uma função que organize as coordenadas (endereços) em sequência de menor distância partindo de A quem é mais perto, digamos que D, e quem é mais perto de D, digamos que B e quem é mais perto de B..... ou seja o array só preserva a posição 0 que é a base e as outras se organizam conforme distância, vou postar o código a partir do array já formado e quem sabe se conseguir reformular, porque não consegui achar uma forma ainda pela minha pouca experiência em javascript.

function reoganizaproximos() {
      for(var i = 0; i < mapcord.length - 1; i++){
      var disMinima=[];
      disMinima.push({'index':0, 'distancia':0});
      for(var f = i + 1; f < mapcord.length; f++){
      testadistancia(function(err, xtalk, i, f){
		var distancia = xtalk;

		if(distancia < disMinima.distancia){
			disMinima.index = f;
			disMinima.distancia = distancia;
		}
	   });	
	 }

	 if(disMinima.index !== i + 1){

		var mapcordTemp = mapcord[i + 1];

		mapcord[i + 1] = mapcord[disMinima.index];
		mapcord[disMinima.index] = mapcordTemp;
	 }
      }
      
 }



function testadistancia(callback) {
        CalculaDistancia(mapcord[i].varlat+','+mapcord[i].varlon,mapcord[f].varlat+','+mapcord[f].varlon)
        .done(function(response){
        var origins = response.originAddresses;
        for (var i = 0; i < origins.length; i++) {
             var results = response.rows[i].elements;
             for (var j = 0; j < results.length; j++) {
                  var xtroca = substituiVirgula(results[j].distance.text);
                  xtalk=parseFloat(xtroca);
                  callback(null, xtalk);
              }
         }
         })
 }

         function substituiVirgula(campo) {
         campo = campo.replace(/,/gi, ".");
         return campo;
         }
     
           function CalculaDistancia(pt1, pt2) { 
                var service = new google.maps.DistanceMatrixService(); 
                var d = $.Deferred();
                service.getDistanceMatrix(
                  { 
                      origins: [pt1], 
                      destinations: [pt2], 
                      travelMode: google.maps.TravelMode.DRIVING, 
                      unitSystem: google.maps.UnitSystem.METRIC,
                      avoidHighways: false,
                      avoidTolls: false
					},   
					 function(response, status){
                      if (status != google.maps.DistanceMatrixStatus.OK) {
                         d.reject(status);
                      } else {
                         d.resolve(response);
                      }
                   });
                   return d.promise(); 
            }

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Similar Content

    • By renan mafra
      Olá pesssoal,

      Sou novato em JS.
      Eu tenho 6 links, que são imagens que quero substituir, uma pela outra.
      Eu sei que poderia fazer isso facilmente via CSS, mas para treinar quero fazer da seguinte forma:

      Minha ideia seria pegar o src das imagens e alterar mudando o nome da imagem, tipo assim:
      Tenho imagens que são os links nomeados assim:    carro.png / carro-B.png (uma imagem(link) é branca e a outra é amarela).

      Como faço para alterar a imagem trocando uma pela outra nesse esquema ?
      <a href="#"><img src="links/carro.png" name="menu0" width="90" height="13" border="0"/></a>
      e trocar para
      <a href="#"><img src="links/carro-B.png" name="menu0" width="90" height="13" border="0"/></a>
       
      Como são 6 imagens eu estou pegando via getElementsByTagName e depois fazer uma função que automatize para todas as outras.....
      Tirando o CSS HOVER via Javascript, essa seria a melhor maneira de automatizar essa troca ?

      vai lá o código:
       
      <html> <head> <style> body{background-color: #000000;} </style> <script> window.onload = function(){ var menu0 = document.getElementsByName("menu0"); var imagem = menu0[0].src; ////////////////////////////////////////////// //bloco que vai varrer cada item: //////////// //for(var i=0; i<menu0.length; i++){ // alert(menu0[i].src); //} ////////////////////////////////////////////// } </script> </head> <body> <a href="#"><img src="links/carro.png" name="menu0" width="90" height="13" border="0"/></a>&nbsp;&nbsp;&nbsp; <a href="#"><img src="links/livro.png" name="menu0" width="86" height="13" border="0"/></a>&nbsp;&nbsp;&nbsp; <a href="#"><img src="links/aviao.png" name="menu0" width="109" height="13" border="0"/></a>&nbsp;&nbsp;&nbsp; <a href="#"><img src="links/motos.png" name="menu0" width="108" height="13" border="0"/></a>&nbsp;&nbsp;&nbsp; <a href="#"><img src="links/bicicleta.png" name="menu0" width="114" height="13" border="0"/></a>&nbsp;&nbsp;&nbsp; <a href="#"><img src="links/onibus.png" name="menu0" width="114" height="13" border="0"/></a> </body> </html> a imagem carro.png tem o seu respectivo carro-B.png
                        aviao.png                                        aviao-B.png
       
      E assim por diante.... Essa é uma boa maneira de fazer isso via JS ?? ou tem melhores ?
       
    • By granderodeo
      Olá tenho a página index.php e tenho a página product.php, ao clicar no produto na página inicial, quero que redirecione para página product.php mostrando os dados do determinado produto que cliquei, iniciei o código mais não está dando certo, Obrigado.
       
      index.php
      <?php if (is_array($products)) { foreach ($products as $id => $row) { ?> <div class="col-sm-6 col-md-4 col-lg-3 mb-2"> <div class="card-deck"> <div class="card p-2 border-secondary mb-2"> <a href="product.php?id=<?= $row['product_id'] ?>"> <div class="hover-image"> <img class="card-img-top border-secondary" src="images/<?= $row['product_image'] ?>"/> <a href="#"><span class="texto"></span></a> </div> </a> <h3 class="text-center"><?= $row['product_name'] ?></h3> <div class="text-center text-black rounded p-1" style="font-size: 20px;">Valor&nbsp;$<?= $row['product_price'] ?></div> <button class="btn btn-success btn-block" type="button" value="Add to cart" onclick="cart.add(<?= $row['product_id'] ?>);">Adicionar ao carrinho</button> </div> </div> </div> <?php } } else { echo "No products found."; } ?>  
      product.php
      <?php $products = $_GET["product_id"]; if (is_array($products)) { foreach ($products as $id => $row) { }}; $row['product_name'] ?>  
    • By 3agdeu
      Bom dia a todos.

      Quero saber se alguns dos sábios participantes saberia um forma que capturar um informação (constantemente atualizada) apresentada em uma aplicação java na tela. São os dados de variação de ações, nos respectivos sites de operações. Geralmente aparecem em um canto fixo ou ficam em um elemento que flutua sobre o gráfico da ação (penso que rodem em java).

      Posso interceptar e interpretar os sinais enviados ao monitor?

      Posso interceptar as atualizações da maquina java e/ou o script?

      Existe um programa para fazer a leitura de uma determinada parte da tela que fica constantemente se atualizando?

      Obrigado.
    • By ChuChun
      Estou começando a mexer com progromação, estive fazendo um algoritmo de física, mas, quando pedi para que fossem coletados os campos para fazer assim a equação, não da certo, este é o código da parte que estou com dificuldade:

       
      $("#btn1").click(function(){ var comprimento = parseFloat($("#comprimento").val()); var espiras = parseFloat($("#espiras").val()); var no = parseFloat($("#no").val()); var multpi = parseFloat($("#multpi").val()); var pi = parseFloat($("#pi").val()); var amperes = parseFloat($("#amperes").val()); var valor = parseFloat($("#valor").val()); var resultado = (var multpi = parseFloat($("#multpi").val() * var pi = parseFloat($("#pi").val()) * parseFloat($("#no").val()) * (parseFloat($("#espiras").val()) * parseFloat($("#comprimento").val()) )* parseFloat($("#amperes").val());  
    • By Kelven
      Existe alguma maneira de meu código não aparecer no código fonte que não seja por meio de Php? Tipo um código javascript que não apareça no código fonte? Quero fazer uma verificação if else se é um determinado valor de uma variável mas sem usar o php pois o blog só aceita javascript, html e css.
×

Important Information

Ao usar o fórum, você concorda com nossos Terms of Use.