I know you already got the answer, but I would like to explain how to use XmlHttpRequest API
.
When you set false
to the third parameter of .open
you are setting it to synchronous:
open('POST', url, false);
Even if you use .onload
or .onreadystatechange
they will not work, understand that Ajax is not the technology but the way we use XmlHttpRequest API
, ie it will only be ajax if it is asynchronous, otherwise it is SJAX ( XmlHttpRequest sync).
See the differences:
Synchronous (this is not Ajax):
var oReq = new XMLHttpRequest();
//Defina como false
oReq.open("GET", "/url", false);
//Espera completar a requisição, geralmente congela o browser
oReq.send(null);
alert(oReq.responseText);
Note that the synchronous "freezes" the webbrowser while the request does not finish
Asynchronous (ie Ajax):
var oReq = new XMLHttpRequest();
//Defina como true
oReq.open("GET", "/url", true);
//Função assíncrona que aguarda a resposta
oReq.onreadystatechange = function()
{
if (oReq.readyState === 4) {
alert(oReq.responseText);
}
};
//Envia a requisição, mas a resposta fica sendo aguardada em Background
oReq.send(null);
Note that the asynchronous does not freeze the browser, because the process is actually in Background and the signal is sent via callback pro .onreadystatechange
to each stage of .readyState
As I explained in this question: Ajax is not a programming language. So what is it?
application/x-www-form-urlencoded
vs multipart/form-data
I understand what TobyMosque said and I do not disagree, just that we need to understand the differences, see setRequestHeader('Content-Type', ...);
is not something just XmlHttpRequest
as you should know, it's an instruction that tells how the data should be interpreted by the back end.
Using new FormData
works perfectly in the way explained, but if we do not have browser support for this class then we have to use application/x-www-form-urlencoded
.
The setRequestHeader('Content-Type', ...);
is equivalent to the enctype
attribute in <form>
, as we define how the form data will be encoded when sending them to the server, there are 3 types of values for this attribute:
-
application/x-www-form-urlencoded
This is the default value in <form>
, but not XmlHttpRequest
. In it all characters are encoded before being sent, for example spaces are exchanged for +
and special characters are converted to HEX ASCII values.
-
-
-
-
-
-
% of spaces are converted to multipart/form-data
signs, but other characters will not be encoded.
Assuming the browser is a bit older and does not support text/plain
then you have to use +
and encode the past in FormData
, like this:
var oReq = new XMLHttpRequest();
//Defina como true
oReq.open("POST", "/url", true);
oReq.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
//Função assíncrona que aguarda a resposta
oReq.onreadystatechange = function()
{
if (oReq.readyState === 4) {
alert(oReq.responseText);
}
};
oReq.send('nome=' + escape('João de Nobrega'));
Or:
oReq.send('nome=' + encodeURIComponent('João de Nobrega'));
If you send without application/x-www-form-urlencoded
they will be in the .send(...);
format and if you do not use application/x-www-form-urlencoded
or RAW
it is likely that it will not recognize what comes after encodeURIComponent
Some details here: Upload does not work $ _FILES undefined index error
Conclusion
Do not use synchronous because it is deprecated and browsers are issuing warnings and in the future will remove the synchronous, so do not use escape
, use João
or omit the third parameter (by default false
uses true
) like this:
request.open('POST', urlBase + '/avaliar-concessionaria/lat-lng');
How the code should stay
As I said, synchronization will soon no longer work in modern browsers, for this you need to understand the difference between callback and return, read this:
Your code should look like this:
function initMap() {
var idDealer = document.getElementById('id-concessionaria').value;
urlBase = document.getElementsByTagName('body')[0].getAttribute('data-base');
var myLatLng, marker, myLatLng; //Torna as variáveis acessíveis no escopo de 'initMap'
var exec = function(lat, lng) {
myLatLng = { "lat": lat, "lng": lng }
map = new google.maps.Map(document.getElementById('mapa'), {
center: myLatLng,
zoom: 10
});
var marker = new google.maps.Marker({
position: myLatLng,
map: map,
title: 'Aqui!'
});
//Resto da função
};
var request = new XMLHttpRequest();
request.open('POST', urlBase + '/avaliar-concessionaria/lat-lng', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
request.onreadystatechange = function() {
if (oReq.readyState === 4 && request.status >= 200 && request.status < 400) {
var data = JSON.parse(request.responseText);
var lat = data[0];
var lng = data[1];
exec(lat, lng);
}
};
request.send("id=" + idDealer);
}
This way it will work asynchronously.