par , 01/02/2016 à 19h39 (1389 Affichages)
- Niveau du billet : moyen.
- Prérequis : ES2015.
- Couverture du sujet : faible. On effleure l'API, on ne parle pas des transactions 'cors', ni de l'utilisation dans un Service Worker.
- Navigateurs compatibles (2016-01-31) avec fetch : Firefox 39+ et Chrome 43+.
- Exemples testés (2016-01-31) avec Chrome 49b (compatible à 91 % avec ES2015).
Une requête "fetch" (asynchrone) retourne une promesse. Une promesse est d'abord en attende ("pending") puis elle est soit tenue ("fufilled") soit rejetée ("rejected").
Lorsque la promesse est tenue, il faut examiner l'état de l'objet "response" pour déterminer si son contenu est exploitable ("response.body" est un objet Stream).
demoFetch0.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| {
fetch( 'cercle.json' ); // erreur volontaire : cercle sans s !
.then( response => {
console.log( 'Content-Type = ', response.headers.get( 'Content-Type' ) );
console.log( 'Date = ', response.headers.get( 'Date' ) );
console.log( 'status = ', response.status );
console.log( 'statusText = ', response.statusText );
console.log( 'type = ', response.type );
console.log( 'url = ', response.url );
})
.catch( er => console.log( er ) );
/*
* Content-Type = application/json
* Date = Sun, 24 Jan 2016 10:04:11 GMT
* status = 404
* statusText = Not found
* type = basic
* url = http://localhost:9080/dvjh/DVP/dvp1/cercle.json
*/
} |
La fonction "processStatus" déterminera si le contenu de nos objets "response" est exploitable. Si le statut est non conforme, on provoque une erreur qui sera interceptée par la méthode "catch".
1 2 3 4 5 6 7 8
| let processStatus = function( r ){
// status "0" to handle local files fetching (e.g. Cordova/Phonegap etc.)
if ( r.status === 200 || r.status === 0 ){
return Promise.resolve( r );
} else {
return Promise.reject( new Error( r.statusText ) );
}
}; |
Méthodes d'exploitation du contenu (response.body)
- response.text() : lis le flux de données et promets de retourner un objet USVString (texte ou html).
- response.json() : lis le flux de données et promets de retourner un objet JSON.
- response.formData() : lis le flux de données et promets de retourner un objet FormData.
- response.blob() : lis le flux de données et promets de retourner un objet Blob.
- response.arrayBuffer() : lis le flux de données et promets de retourner un objet ArrayBuffer.
Exemples
1) La méthode json transforme ("parse") le contenu ("body") de l'objet "response" en objet JS ("data").
demoFetch1.html
1 2 3 4 5 6 7 8 9 10 11
| {
fetch( 'cercles.json' )
.then( r => processStatus( r ) )
.then( r => r.json() )
.then( data => {
for ( let elem of data.nodes ){
console.log( elem );
}
})
.catch( er => console.log( er ) );
} |
2) Équivalent d'une transaction AJAX avec l'objet "FormData".
On envoie ("post") les données du formulaire au serveur et on affiche sa réponse.
demoFetch2.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| {
let myForm = document.querySelector( '#myForm' );
myForm.addEventListener( 'submit', function( ev ){
ev.preventDefault();
ev.stopPropagation();
fetch( 'test3.php', {
'method' : 'post',
'body' : new FormData( myForm )
})
.then( r => processStatus( r ) )
.then( r => r.text() )
.then( text => console.log( text ) )
.catch( er => console.log( er ) );
}, false);
} |
3) Chargement et utilisation d'un script JS, le plugin jquery color.
demoFetch3.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| {
fetch( 'https://code.jquery.com/color/jquery.color.js' )
.then( r => processStatus( r ) )
.then( r => r.blob() )
.then( myBlob => {
let el = document.createElement( 'script' );
el.type = 'text/javascript';
el.async = false;
el.src = URL.createObjectURL( myBlob );
document
.querySelector( 'head' )
.appendChild( el );
$( '#go' ).on( 'click', function(){
$( ".block" )
.animate({ 'backgroundColor' : 'rgb(255, 180, 180)' }, 1000 )
.delay( 500 )
.animate({ 'backgroundColor' : 'olive' }, 1000 )
.delay( 500 )
.animate({ 'backgroundColor' : '#00f' }, 1000 );
});
})
.catch( er => console.log( er ) );
} |
4) Lecture récursive d'un flux de données ("response.body" est un objet Stream).
On transforme les données ("Uint8Array") avec "TextDecoder" et on stocke le résultat ("text/html") dans la variable "buffer".
Lorsque la lecture du flux est terminée, on procède à l'affichage du HTML.
demoFetch4.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
| {
fetch( 'https://html.spec.whatwg.org/' )
.then( r => processStatus( r ) )
.then( r => {
/*
* getReader () nous donne un accès exclusif
* au contenu du flux
*/
let
reader = r.body.getReader(),
decoder = new TextDecoder(),
buffer = '',
bytesReceived = 0;
reader
.read()
.then( function processResult( result ){
/*
* L'objet result contient les propriétés
* done (booléen) et value (les données).
*
* Lorsque done est vrai (true), value est
* vide, la lecture du Stream est terminée.
*
* result.value est un Uint8Array, il sera
* transformé en HTML par TextDecoder.
*/
if ( result.done ){
console.log( "Lecture du flux terminée." );
let el = document.createElement( 'div' );
el.innerHTML = buffer;
document
.querySelector( 'body' )
.appendChild( el );
/*
* Après quelques instants de patience le contenu de
* buffer s'ajoute à votre page web.
*
* La console signale que les liens relatifs vers
* les images sont brisés, c'est normal. Mais le
* HTML est exloitable.
*/
return;
}
bytesReceived += result.value.length;
console.log( `Nous avons reçu ${bytesReceived} bytes de données` );
buffer += decoder.decode( result.value, { 'stream' : true } );
// lecture récursive
return reader.read().then( processResult );
});
})
.catch( er => console.log( er ) );
} |