Ajax sobre ajax, cómo?

eXtreM3

Buenas, veréis, tengo una aplicación web que verifica una serie de códigos de barras que entran desde un input.

El proceso es:

  • El focus siempre está puesto en el input.
  • Con el lector de códigos leo el código que esté impreso.
  • Se guarda por post en la base de datos local.

En este punto, también necesito que esos mismos valores se guarden en una base de datos espejo en otro servidor. En el servidor B tengo un controlador que es el que se encarga de insertar los datos ahí, y lo invoco por ajax.

Es decir, en mi aplicación, en el momento en el que se inserta en la base de datos local, hago esto:

$.ajax({
    url: 'http://servidorB.com/controlador/_random_string_',
    dataType: 'json',
    success: function( response ) {
        if(response.status == 'ok'){
            console.log('done');
        }
    }
});

y lo guarda bien en la base de datos remota. Ahora, en este punto, necesito que el controlador (que se ha ejecutado asíncronamente y es transparente al usuario) devuelva a mi aplicación algo para realizar la siguiente operación: actualizar un campo en la base de datos local.

¿Cómo hago esto? He probado a hacer un "header location" desde el controlador pero no ejecuta nada. Si abro la llamada del controlador al invocar el primer ajax (esta url: http://localhost/proyecto/random_string) sí que redirige correctamente y me actualiza mi campo en la base de datos local. Pero claro, como el controlador del servidor B se ha ejecutado asíncronamente, no hace nada por el funcionamiento natural.

¿Alguna idea?

DarkSoldier

#1 hola :-D

a ver que me aclare, tienes una aplicación web en local que lee un código de barras y lo guarda en la base de datos local y quieres que a su vez se guarden en un servidor remoto?

1 respuesta
eXtreM3

#2 sí, y todo eso ya lo tengo hecho. Lo que me falta es que mi aplicación local detecte que el código ha sido insertado en la base de datos remota, y si está insertado pues ejecuto otro código en local.

Acaba de ocurrírseme al vuelo que después de lanzar la petición ajax que inserta en la bd remota, realizar una consulta a dicha base de datos y si está insertado ejecuto mi código local.

Pero era por saber si se podía hacer más "limpiamente" desde el controlador remoto, si hay manera de devolver algo.

1 respuesta
DarkSoldier

#3 en el response tienes los datos que te devuelve el controller, puedes devolver un { result: true } si se ha insertado o un { result: false } si falla, si es true pues blabla en local, no te serviría?

1 respuesta
eXtreM3

#4 no devuelve nada ese response, se queda como en el limbo de las cosas asíncronas xD

1 respuesta
DarkSoldier

#5 al poner dataType espera recibir un JSON tienes que poner en el controller algo así:

header('Content-Type: application/json');
echo json_encode(array('result' => true));
2 respuestas
eXtreM3

#6 pero estás seguro de que esa respuesta la recibe aunque el controlador se ejecute de manera asíncrona?? Lo he probado antes y no funcionaba, voy a volver a probar por si me he equivocado en algo.

2 respuestas
Kiroushi

#7 ¿Es mysql o mariadb? ¿No te sirve un master-slave?

2 respuestas
eXtreM3

#8 mysql, pero qué importa el motor de la base de datos aquí?

#6 no funciona. Si ejecuto la url directamente en el navegador sí me tira la respuesta por json, pero si carga el php asíncronamente no devuelve nada. Ffffffffffuuuuuuuuu!

1 respuesta
DarkSoldier

#7 hombre el success se ejecuta cuando ha el request ha ido bien, luego tienes el error para comprobar si falla y el complete para que pase lo que pase muestre algo

edit: metele un complete: function(data) { console.log(data); } a ver que devuelve ese data
ninjaedit2: respecto a lo que dice #8, tiene mejor pinta y supongo que será mas estable que controlar dos peticiones (https://www.digitalocean.com/community/tutorials/how-to-set-up-master-slave-replication-in-mysql), lo guardas en local y que replique en remoto no?

1 respuesta
eXtreM3

#10 acabo de ver esto en la consola del navegador:

 XMLHttpRequest cannot load http://servidorB.com/controlador/_string_. 
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.
1 respuesta
DarkSoldier

#11 CORS IS COMING xDDDD tienes que configurar el servidor remoto para que acepte peticiones desde otros servidores

1 respuesta
eXtreM3

#12 pero si las peticiones las acepta, en la base de datos remota me está guardando los datos correctamente!

He añadido el "error" al ajax y entra ahí, me ha sacado por consola un mensaje que he puesto cuando da error. mmmmmmmmmmmmmmmmmmmmm en realidad creo que ya me serviría, porque lo que quería era obtener una respuesta, la que fuera xD al terminar la operación en el servidor remoto.

2 respuestas
DarkSoldier

#13 ese error que has mostrado significa que el servidorB no acepta peticiones de localhost, no se como has llegado a ese error pero significa eso (he tenido problemas con CORS hace muy poco xD)

1 respuesta
eXtreM3

#14 qué significa que "no acepta peticiones desde localhost" pero sí guarda los datos en la base de datos? Acepta o no acepta? xD

2 respuestas
DarkSoldier

#15 no debería si te sale ese error vamos XD esa petición ha sido denegada, abre consola y ves a network (pestaña XHR) y verás como te sale en rojo con un error

1 respuesta
RaymaN

#15 con ajax no puedes hacer una petición desde el propio servidor a otro si este no lo configuras explícitamente.

1 respuesta
Kiroushi

#9 ¿Cómo que qué tiene que ver? Tienes la posibilidad de hacer un replicado master-slave que sabes que no va a fallar, incluso si el esclavo está caído en un momento determinado.

eXtreM3

#16 no sale en rojo, sale normal. El error ese sale en la consola :\

CCiRviNe

#13 Prueba a ejecutarlo en chrome/chromium iniciado con el parámetro --disable-web-security

1 respuesta
eXtreM3

Vale, por partes. Es problema de CORS, por alguna razón el servidor B no acepta peticiones externas, aunque sí me guarda en la base de datos.

#17 cómo lo configuro para que acepte peticiones desde localhost? He probado lo primero que he visto de añadir en el htaccess allow from 127.0.0.1 pero no tira bien.

#20 he instalado esta extensión de Chrome https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi/related que hace eso que dices, y ahora sí funciona perfectamente, devuelve el response del ajax con el que invoqué el controlador

Cómo lo hago por código en vez de instalando esa extensión?

eXtreM3

Solucionado. Este código al principio de mi método en el controlador y funcionando, justo lo que quería.

header("Access-Control-Allow-Origin: *");

Gracias a todos.

1
RaymaN

De todas formas lo mejor sería que la petición se hiciese desde localhost a servidor B al guardar correctamente los datos, así evitas delegar en el cliente una función que asumo es importante.

B

Creo que jamás deberías solucionar ese problema en la capa de aplicación. Y cuidadito con esto:

header("Access-Control-Allow-Origin: *");

que dejas un boquete precioso.

1 1 respuesta
S

Me parece que estas solucionando el problema mal.
A grandes rasgos tu app solo debería hacer una petición ajax y tu servidor encargarse de hacer toda esta tarea que te esta dando problemas. Eso de estar enviando peticiones por ajax a distintos servidores esta simplemente mal y la solución que le acabas dando al embrollo en el que te metes mal también.

1 respuesta
Kiroushi

#25 -> #8

eXtreM3

¿Qué consecuencias puede tener mi solución?

#24 no hay boquete posible, ese controlador únicamente se dedica a esta tarea.

Pregunto, entre peticiones no estoy muy puesto, sólo sé que lo que he hecho funciona y teóricamente he hecho bastantes debugs sobre accesos y restricciones.

1 respuesta
CCiRviNe

Que entre la petición al servidor A y la petición al servidor B se le vaya la conexión al cliente, quedarían los datos en A pero no en B.

1 respuesta
eXtreM3

#28 eso está controlado, para eso tengo el campo "actualizado" en A que es el que actualizo cuando recibo la petición desde B. Si se va internet no pasa nada, cuando vuelva recorro todos los que están sin actualizar y si están en B los actualizo, si no los subo a B y actualizo.

B

#27 No se, por lo que has enseñado hay un endpoint que replica datos con el cors abierto de par en par, si no ves un agujero ahí que quieres que te diga...

1

Usuarios habituales