Je suppose que vous savez comment faire une requête XHR native (vous pouvez brosser ici et ici )
Étant donné que tout navigateur qui prend en charge les promesses natives le prendra également en charge xhr.onload, nous pouvons ignorer toute la onReadyStateChangefolie. Prenons du recul et commençons par une fonction de requête XHR de base utilisant des rappels:
function makeRequest (method, url, done) {
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
done(null, xhr.response);
};
xhr.onerror = function () {
done(xhr.response);
};
xhr.send();
}
// And we'd call it as such:
makeRequest('GET', 'http://example.com', function (err, datums) {
if (err) { throw err; }
console.log(datums);
});
Hourra! Cela n'implique rien de très compliqué (comme des en-têtes personnalisés ou des données POST) mais suffit pour nous faire avancer.
Le constructeur de promesses
Nous pouvons construire une promesse comme ceci:
new Promise(function (resolve, reject) {
// Do some Async stuff
// call resolve if it succeeded
// reject if it failed
});
Le constructeur de promesse prend une fonction qui recevra deux arguments (appelons-les resolveet reject). Vous pouvez les considérer comme des rappels, un pour le succès et un pour l'échec. Les exemples sont géniaux, mettons à jour makeRequestavec ce constructeur:
function makeRequest (method, url) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.response);
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
xhr.send();
});
}
// Example:
makeRequest('GET', 'http://example.com')
.then(function (datums) {
console.log(datums);
})
.catch(function (err) {
console.error('Augh, there was an error!', err.statusText);
});
Maintenant, nous pouvons puiser dans la puissance des promesses, enchaînant plusieurs appels XHR (et le .catchdéclenchera une erreur sur l'un ou l'autre appel):
makeRequest('GET', 'http://example.com')
.then(function (datums) {
return makeRequest('GET', datums.url);
})
.then(function (moreDatums) {
console.log(moreDatums);
})
.catch(function (err) {
console.error('Augh, there was an error!', err.statusText);
});
Nous pouvons encore améliorer cela, en ajoutant à la fois des paramètres POST / PUT et des en-têtes personnalisés. Utilisons un objet options au lieu de plusieurs arguments, avec la signature:
{
method: String,
url: String,
params: String | Object,
headers: Object
}
makeRequest ressemble maintenant à quelque chose comme ceci:
function makeRequest (opts) {
return new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open(opts.method, opts.url);
xhr.onload = function () {
if (this.status >= 200 && this.status < 300) {
resolve(xhr.response);
} else {
reject({
status: this.status,
statusText: xhr.statusText
});
}
};
xhr.onerror = function () {
reject({
status: this.status,
statusText: xhr.statusText
});
};
if (opts.headers) {
Object.keys(opts.headers).forEach(function (key) {
xhr.setRequestHeader(key, opts.headers[key]);
});
}
var params = opts.params;
// We'll need to stringify if we've been given an object
// If we have a string, this is skipped.
if (params && typeof params === 'object') {
params = Object.keys(params).map(function (key) {
return encodeURIComponent(key) + '=' + encodeURIComponent(params[key]);
}).join('&');
}
xhr.send(params);
});
}
// Headers and params are optional
makeRequest({
method: 'GET',
url: 'http://example.com'
})
.then(function (datums) {
return makeRequest({
method: 'POST',
url: datums.url,
params: {
score: 9001
},
headers: {
'X-Subliminal-Message': 'Upvote-this-answer'
}
});
})
.catch(function (err) {
console.error('Augh, there was an error!', err.statusText);
});
Une approche plus globale peut être trouvée chez MDN .
Vous pouvez également utiliser l' API fetch ( polyfill ).