1

Existe una API que tiene varios métodos para solicitarle datos, entre ellos, un método me entrega la lista de códigos de órdenes de trabajo que se ingresaron en una fecha determinada para un cliente específico.

api.ot/ot.json?fecha=26062018&CodigoCliente=100448&ticket=A8537A18-6766

El ticket es sólo un token para validar la petición por parte de la API. Esta lista de órdenes de trabajo la almaceno en un arreglo.

Una vez que tengo la lista de órdenes de trabajo, consulto la API con otro método, el cual me entrega el detalle de cada orden de trabajo recuperada en la consulta anterior.

api.ot/ot.json?codigo="+ot[j]+"&ticket= A8537A18-6766

En donde ot[j] es una orden de trabajo almacenada en la primera consulta.

Ambas peticiones las hago con Ajax y la situación que me tiene complicado es:

1) La primera consulta Ajax retorna correctamente las órdenes de trabajo, las cuales se almacenan en un arreglo ot[].

2) Cuando hago las consultas de los detalles de cada orden de trabajo, la API me devuelve el siguiente mensaje

“Lo sentimos. Hemos detectado que existen peticiones simultaneas”.

La implementación es la siguiente:

<!DOCTYPE html>
<html>
  <head>
    <script 

   src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"> 
    </script>
  <script>
    $(document).ready(function()
    {
      $("#btn_nuevo").click(function()
      {
        var ocs=[];
        var total=0;          
        //SE OBTIENEN LAS ORDENES DE TRABAJO
        $.ajax(
          {
              url: "http://api.ot/ot.json?fecha=26062018&CodigoCliente=100448&ticket=A8537A18-6766",
              dataType: "json",
              success : function(data)
              {
              total=data.Cantidad;
              //SE ALMACENAN LAS OT
              for (var i = 0; i < total; i++) 
              {
                ot[i+1]=data.Listado[i].Codigo;                
              };
              //SE RECUPERA EL DETALLE DE LAS OT
            for (var j = 0; j < total ; j++)
            {
              var url="http://api.ot/ot.json?codigo="+ot[j]+"&ticket= A8537A18-6766";
              $.ajax(
                {            
                  url: url,
                  dataType: "json",
                  success : function(datos) 
                  {             
                    $('#result').append('<b>Codigo: </b>' + datos.Listado[0].Codigo +'<br />');
                    $('#result').append('<b>Nombre: </b>' + datos.Listado[0].Nombre +'<br />');
                    $('#result').append('<b>Estado: </b>' +datos.Listado[0].Estado +'<br />');
                    $('#result').append('<b>Descripcion: </b>' + datos.Listado[0].Descripcion +'<br />');
                    $('#result').append('<b>Tipo: </b>' + datos.Listado[0].Tipo +'<br />');                      
                  },
                }
                ); 
            };
            }
            }
            );
      });
    });

  </script>
</head>
<body>
  <div id="boton_nuevo" align="center">
    <input type="button" id="btn_nuevo" name="btnnuevo" value="Extraer">
  </div>
  <div id="result"></div>     
</body>
</html>

La respuesta de la API para la primera consulta Ajax está correcta, trayendo la lista de las órdenes de trabajo, pero cuando se comienzan a enviar las consultas de los detalles de las órdenes de trabajo, aparece un "500 Internal Server Error" y la respuesta que llega es:

{"Codigo":10500,"Mensaje":"Lo sentimos. Hemos detectado que existen peticiones simultáneas."}

Cómo se puede solucionar esta situación, entendiendo que lo que se requiere recuperar es el detalle de cada orden de trabajo.

En base al aporte de Pablo Lozano, hice las modificaciones:

<!DOCTYPE html>
<html>      
  <head>
    <script 
    src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"> 
    </script>
    <script>
    $(document).ready(function()
    {
      $("#btn_nuevo").click(function()
      {
        var ocs=[];
        var total=0;
        $('#result').append('<b>total 1: </b>' + total +'<br />');

        //ESTE PRIMER AJAX OBTIENE LA LISTA DE OT
        $.ajax({
          url: "http://api.ot/ot.json?fecha=26062018&CodigoCliente=100448&ticket=A8537A18-6766",
          dataType: "json",
          success : function(data)
          {
            //TOTAL DE OT
            total=data.Cantidad;

            //SE ALMACENAN LAS OT
            for (var i = 0; i < total; i++) 
            {
              ocs[i+1]=data.Listado[i].Codigo               
            };
            //APORTE DE PABLO LOZANO
            var promise;
            var j = 0
            var url = "http://api.ot/ot.json?codigo="+ot[j]+"&ticket= A8537A18-6766";

            for (var j = 0; j < total ; j++)
            {
              if(j=0)
              {
                promise = promise || $.ajax({ url: url, dataType: "json"});
                j++
              }
              else
              {
                promise = promise.then(datos => {
                  $('#result').append('<b>Codigo: </b>' + datos.Listado[0].Codigo + '<br />');
                  $('#result').append('<b>Nombre: </b>' + datos.Listado[0].Nombre + '<br />');
                  $('#result').append('<b>Estado: </b>' + datos.Listado[0].Estado + '<br />');
                  $('#result').append('<b>Descripcion: </b>' + datos.Listado[0].Descripcion + '<br />');
                  $('#result').append('<b>Tipo: </b>' + datos.Listado[0].Tipo + '<br />');
                  url = "http://api.ot/ot.json?codigo="+ot[j]+"&ticket= A8537A18-6766";
                  return $.ajax({url: url, dataType: "json",});
                })
              }
            };                
          }            
        });
      });
    });

  </script>
</head>
<body>
  <div id="boton_nuevo" align="center">
    <input type="button" id="btn_nuevo" name="btnnuevo" value="Ejecutar">
  </div>
  <div id="result"></div>     
</body>
</html>

Al ejecutar arroja el siguiente error:

TypeError: promise is undefined

Cómo codifico la implementación de promise en Jquery?

alo Malbarez
  • 8,871
  • 2
  • 10
  • 29
Junco Fuerte
  • 659
  • 5
  • 13
  • 29
  • tendrías que encadenar los ajax del for, para que no sean simultáneas. averigua con el responsable del API si no hay una forma de traer todo en una sola consulta (en la primera) o con dos y la segunda que acepte un array de ids. en la segunda peticion si pasas un array o cadena separada por comas a codigo da error? – alo Malbarez Jul 03 '18 at 16:03
  • Cómo se pueden encadenar los ajax del for?, entiendo la idea de fondo, pero no sé cómo se implementa. – Junco Fuerte Jul 03 '18 at 16:27
  • Pablo te da una respuesta al cómo hacerlo, lo que se complicaría sería recibir un "demasiadas peticiones" si hay un límite por tiempo – alo Malbarez Jul 03 '18 at 16:38
  • 1
    error 500 es del servidor, parece que no esta configurado para recibir multiples solicitudes en simultáneo, algo que puedes hacer es ir trayendo de una, el for no es sincrónico por lo que va a disparar todas tan pronto como pueda, pero si tu puedes encadenarlas de manera que el success de una petición llame a la siguiente lo más probable es que no tengas el error que estas viendo. Esto tiene una implicación en tiempo de ejecución, pero es una solución si no tienes acceso al backend – Daniel Torres Laserna Jul 03 '18 at 16:06

1 Answers1

0

La solución sería no hacer las llamadas en paralelo, sino una detrás de otra. Lo malo es que el tiempo de espera se agrandará:

let promise;
let j = 0
let url = `http://api.ot/ot.json?codigo=${ot[j]}&ticket= A8537A18-6766`;
for (let j = 0;j < total,j++) {

    //Si no hemos hecho ninguna llamada, se hace la primera de todas
    //en otro caso (j>0), esta línea no hace nada
    promise = promise || $.ajax({ url: url, dataType: "json" });
    j++;

    //encadenamos las llamadas, cada vez que tengamos una respuesta hacemos otra
    promise = promise.then(datos => {
        $('#result').append('<b>Codigo: </b>' + datos.Listado[0].Codigo + '<br />');
        $('#result').append('<b>Nombre: </b>' + datos.Listado[0].Nombre + '<br />');
        $('#result').append('<b>Estado: </b>' + datos.Listado[0].Estado + '<br />');
        $('#result').append('<b>Descripcion: </b>' + datos.Listado[0].Descripcion + '<br />');
        $('#result').append('<b>Tipo: </b>' + datos.Listado[0].Tipo + '<br />');
        let url = `http://api.ot/ot.json?codigo=${ot[j]}&ticket= A8537A18- 6766`;
        return $.ajax({
            url: url,
            dataType: "json",
        });
    })
}   
Pablo Lozano
  • 45,934
  • 7
  • 48
  • 87
  • Pablo, el código que pusiste está implementado en qué lenguaje? – Junco Fuerte Jul 03 '18 at 17:10
  • Javascript, claro. Uso el estándar de 2015 – Pablo Lozano Jul 03 '18 at 21:56
  • Pablo, implementé lo que me sugeriste, pero me arroja un error. He actualizado el cuerpo de la pregunta con la recodificación aplicada. Por favor, me puedes ayudar para solucionar el problema. – Junco Fuerte Jul 04 '18 at 15:54
  • `if (j=0) {` debería ser `if (j===0) {` (usa 3 veces el símbolo igual por norma, te ahorrará problemas) – Pablo Lozano Jul 04 '18 at 15:56
  • Dado que dudaste del lenguaje que estaba usando en mi respuesta, quizá te ayude a entender el código esta otra respuesta: https://es.stackoverflow.com/questions/106042/var-let-const-o-nada-en-javascript/106067#106067 – Pablo Lozano Jul 04 '18 at 16:03
  • Hice los cambios if(j===0) y cambié los var por let, tal como lo habías escrito. Ejecuté y no trae los detalles de las OT. Revisando, veo que hay un mensaje que envía el servidor "Estado:Error 500" y {"Codigo":10500,"Mensaje":"Lo sentimos. Hemos detectado que existen peticiones simultáneas."}. en la versión original mía, cuando lo hacía sin promise, el servidor arrojaba una lista de Error 500, una por cada consulta de detalle. Ahora con la modificación, sólo envía un mensaje de error 500. – Junco Fuerte Jul 04 '18 at 17:01
  • si falla la primera no se hacen mas – Pablo Lozano Jul 05 '18 at 12:00
  • La pregunta que me cabe hacer y disculpa mi ignorancia en el tema, es si este error es por un tema de encadenamiento entre el primer Ajax que recupera la lista de OT y el segunda Ajax que recupera el detalle de las OT, o es por un problema en la implementación del secuenciamiento con promise?, pues no entiendo cuáles son las peticiones concurrente en este caso. – Junco Fuerte Jul 05 '18 at 14:57
  • Si te soy sincero yo tampoco lo acabo de enteder, las peticiones deberían hacerse de una en una – Pablo Lozano Jul 05 '18 at 15:12