javascript - synchroniser - js when




Les promesses ne sont-elles pas juste des rappels? (5)

Aucune promesse n'est juste un emballage sur les rappels

exemple Vous pouvez utiliser des promesses natives javascript avec le noeud js

my cloud 9 code link : https://ide.c9.io/adx2803/native-promises-in-node

/**
* Created by dixit-lab on 20/6/16.
*/

var express = require('express');
var request = require('request');   //Simplified HTTP request client.


var app = express();

function promisify(url) {
    return new Promise(function (resolve, reject) {
    request.get(url, function (error, response, body) {
    if (!error && response.statusCode == 200) {
        resolve(body);
    }
    else {
        reject(error);
    }
    })
    });
}

//get all the albums of a user who have posted post 100
app.get('/listAlbums', function (req, res) {
//get the post with post id 100
promisify('http://jsonplaceholder.typicode.com/posts/100').then(function (result) {
var obj = JSON.parse(result);
return promisify('http://jsonplaceholder.typicode.com/users/' + obj.userId + '/albums')
})
.catch(function (e) {
    console.log(e);
})
.then(function (result) {
    res.end(result);
}
)

})


var server = app.listen(8081, function () {

var host = server.address().address
var port = server.address().port

console.log("Example app listening at http://%s:%s", host, port)

})


//run webservice on browser : http://localhost:8081/listAlbums

Je développe JavaScript depuis quelques années et je ne comprends pas le tapage sur les promesses du tout.

Il semble que tout ce que je fais est de changer:

api(function(result){
    api2(function(result2){
        api3(function(result3){
             // do work
        });
    });
});

Lequel je pourrais utiliser une bibliothèque comme async de toute façon, avec quelque chose comme:

api().then(function(result){
     api2().then(function(result2){
          api3().then(function(result3){
               // do work
          });
     });
});

Ce qui est plus de code et moins lisible. Je n'ai rien gagné ici, ce n'est pas soudainement "plat" non plus. Sans parler de devoir convertir les choses en promesses.

Alors, quel est le gros problème des promesses ici?


En plus des autres réponses, la syntaxe ES2015 se mélange parfaitement avec les promesses, réduisant encore plus le code standard:

// Sequentially:
api1()
  .then(r1 => api2(r1))
  .then(r2 => api3(r2))
  .then(r3 => {
      // Done
  });

// Parallel:
Promise.all([
    api1(),
    api2(),
    api3()
]).then(([r1, r2, r3]) => {
    // Done
});

En plus des réponses impressionnantes d' Oscar et Bergi , avec les fonctions de flèches ES6, Promises passe d'une petite étoile bleue modestement brillante à une géante rouge. C'est sur le point de s'effondrer dans une supernova:

api().then(result => api2()).then(result2 => api3()).then(result3 => console.log(result3))

Les promesses ne sont pas des rappels, les deux sont des idiomes de programmation qui facilitent la programmation asynchrone. L'utilisation d'une programmation de type async / await utilisant des coroutines ou des générateurs qui renvoient des promesses pourrait être considérée comme un troisième idiome de ce type. Une comparaison de ces idiomes entre différents langages de programmation (y compris Javascript) est ici: https://github.com/KjellSchubert/promise-future-task


Oui, les promesses sont des rappels asynchrones. Ils ne peuvent rien faire que les callbacks ne peuvent pas faire, et vous faites face aux mêmes problèmes avec l'asynchronie qu'avec les callbacks simples.

Cependant, les promesses sont plus que de simples rappels. Ils sont une abstraction très puissant, permettent un code plus propre et meilleur, fonctionnel avec moins d'erreurs.

Alors, quelle est l'idée principale?

Les promesses sont des objets représentant le résultat d'un calcul unique (asynchrone). Ils se résolvent à ce résultat une seule fois. Il y a quelques petites choses que cela signifie:

Les promesses mettent en œuvre un modèle d'observateur:

  • Vous n'avez pas besoin de connaître les rappels qui utiliseront la valeur avant la fin de la tâche.
  • Au lieu d'attendre des callbacks comme arguments pour vos fonctions, vous pouvez facilement return un objet Promise
  • La promesse stockera la valeur, et vous pouvez ajouter de manière transparente un rappel quand vous le souhaitez. Il sera appelé quand le résultat sera disponible. "Transparence" implique que lorsque vous avez une promesse et que vous y ajoutez un rappel, cela ne change rien à votre code si le résultat est déjà arrivé - l'API et les contrats sont identiques, ce qui simplifie beaucoup la mise en mémoire cache.
  • Vous pouvez facilement ajouter plusieurs rappels

Les promesses sont chaînables ( monadiques , si vous voulez):

  • Si vous devez transformer la valeur représentée par une promesse, vous mappez une fonction de transformation sur la promesse et récupérez une nouvelle promesse représentant le résultat transformé. Vous ne pouvez pas obtenir de manière synchrone la valeur pour l'utiliser d'une manière ou d'une autre, mais vous pouvez facilement lever la transformation dans le contexte de la promesse. Pas de rappels standard.
  • Si vous souhaitez chaîner deux tâches asynchrones, vous pouvez utiliser la méthode .then() . Il faudra un rappel pour être appelé avec le premier résultat, et renvoie une promesse pour le résultat de la promesse que le rappel retourne.

Cela semble compliqué? Temps pour un exemple de code.

var p1 = api1(); // returning a promise
var p3 = p1.then(function(api1Result) {
    var p2 = api2(); // returning a promise
    return p2; // The result of p2 …
}); // … becomes the result of p3

// So it does not make a difference whether you write
api1().then(function(api1Result) {
    return api2().then(console.log)
})
// or the flattened version
api1().then(function(api1Result) {
    return api2();
}).then(console.log)

Aplatir ne vient pas comme par magie, mais vous pouvez le faire facilement. Pour votre exemple fortement imbriqué, l'équivalent (proche) serait

api1().then(api2).then(api3).then(/* do-work-callback */);

Si voir le code de ces méthodes aide à comprendre, voici une promesse la plus basique en quelques lignes .

Quel est le gros problème des promesses?

L'abstraction Promise permet une bien meilleure composabilité des fonctions. Par exemple, à côté du chaînage, la fonction all crée une promesse pour le résultat combiné de plusieurs promesses en attente parallèle.

Last but not least Les promesses sont accompagnées d'une gestion intégrée des erreurs. Le résultat du calcul peut être que soit la promesse est remplie avec une valeur, soit elle est rejetée avec une raison. Toutes les fonctions de composition gèrent cela automatiquement et propagent les erreurs dans les chaînes de promesses, de sorte que vous n'avez pas besoin de vous en soucier explicitement partout - contrairement à une implémentation de callback simple. À la fin, vous pouvez ajouter un rappel d'erreur dédié pour toutes les exceptions survenues.

Sans parler de devoir convertir les choses en promesses.

C'est plutôt trivial avec de bonnes bibliothèques de promesses, voir Comment convertir une API de rappel existante en promesses?







bluebird