Voir le flux RSS

danielhagnoul

Fetch tient ses promesses (découverte du sujet et premiers essais).

Noter ce billet
par , 01/02/2016 à 19h39 (490 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

Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
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".

Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
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)

  1. response.text() : lis le flux de données et promets de retourner un objet USVString (texte ou html).
  2. response.json() : lis le flux de données et promets de retourner un objet JSON.
  3. response.formData() : lis le flux de données et promets de retourner un objet FormData.
  4. response.blob() : lis le flux de données et promets de retourner un objet Blob.
  5. 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

Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
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

Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
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

Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
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

Code javascript : Sélectionner tout - Visualiser dans une fenêtre à part
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 ) ); 
}

Envoyer le billet « Fetch tient ses promesses (découverte du sujet et premiers essais). » dans le blog Viadeo Envoyer le billet « Fetch tient ses promesses (découverte du sujet et premiers essais). » dans le blog Twitter Envoyer le billet « Fetch tient ses promesses (découverte du sujet et premiers essais). » dans le blog Google Envoyer le billet « Fetch tient ses promesses (découverte du sujet et premiers essais). » dans le blog Facebook Envoyer le billet « Fetch tient ses promesses (découverte du sujet et premiers essais). » dans le blog Digg Envoyer le billet « Fetch tient ses promesses (découverte du sujet et premiers essais). » dans le blog Delicious Envoyer le billet « Fetch tient ses promesses (découverte du sujet et premiers essais). » dans le blog MySpace Envoyer le billet « Fetch tient ses promesses (découverte du sujet et premiers essais). » dans le blog Yahoo

Mis à jour 07/02/2016 à 11h06 par danielhagnoul

Tags: es2015, fetch, stream
Catégories
Javascript , Développement Web

Commentaires