En utilisant des promesses Javascript natives, résolvez une promesse après les objects attachables

Existe-t-il un moyen d’utiliser une promesse ( docs ) native javascript pour créer une promesse et y attacher des tables, sans savoir au moment de la construction comment cela va se résoudre?

var foo = new Promise(function(resolve, reject) { // I don't know how this will resolve yet as some other object will resolve it }); foo.then(function(val) { console.log("first " + val); }); foo.resolve("bar"); foo.then(function(val) { console.log("second " + val); }); // result // first bar // second bar 

Il suffit de les sauvegarder à l’intérieur d’une fermeture.

 var makePromise = function () { var resolvePromise = null, rejectPromise = null, promise = new Promise(function (resolve, reject) { resolvePromise = resolve; rejectPromise = reject; }); return { promise : promise, resolve : resolvePromise, reject : rejectPromise }; }; var deferredSomething = function () { var deferredThing = makePromise(); waitAWhile() .then(doStuff) .then(function (result) { if (result.isGood) { deferredThing.resolve(result.data); } else { deferredThing.reject(result.error); } }); return deferredThing.promise; }; 

C’est en fait la majeure partie de la différence entre le concept “différé” et le concept “promesse”; Un autre niveau, en plus, contient les télécommandes que vous pouvez donner à quelqu’un d’autre, tandis que vous .then|.success|.done|etc... le .then|.success|.done|etc... à vos consommateurs.

Une fois que vous avez introduit ces fonctions dans votre processus en amont, vous pouvez charger paresseusement ce que vous voulez, en utilisant le “thenable” que vous retournerez, puis réussir ou échouer votre chaîne (ou la laisser pendre) à volonté. ..

METTRE À JOUR

Voyant que cela va probablement continuer à être la réponse choisie et continuer à être rejetée, en tant que solution au problème exact qu’il avait (par exemple: code de modification qui n’a pas été fait avec les promesses ES6 à l’esprit), je me figure Ajoutons un exemple plus détaillé expliquant précisément pourquoi utiliser cet anti-modèle de manière sélective peut être mieux que rien:

 MongoClient.connect("mongodb://localhost:21017/mydb", (err, db) => { db.collection("mycollection", (err, collection) => { collection.find().toArray((err, results) => { doStuff(results); }); }); }); 

Si je devais écrire une bibliothèque, ici, dans l’espoir d’atteindre le point où je pourrais écrire:

 let dbConnected = MongoClient.connect(dbURL); dbConnected .then(db => db.collection(myCollection)) .then(collection => collection.find(query)) .then(stream => doStuff(stream)); 

…Ou bien:

 composeAsync( (stream) => doStuff(stream), (collection) => collection.find(query), (db) => dbCollection(myCollection) )(dbConnected); 

… pour faciliter l’utilisation dans la bibliothèque, est-il judicieux d’envelopper chaque corps de fonction dans une promesse instanciée // find = curry (requête, collection) renvoyer une nouvelle promesse (résoudre, rejeter) {/ * tout le corps de la fonction , ici / / fait beaucoup de choses qui ne sont pas pertinentes pour la résolution de mongo.db.collection.find, mais qui sont pertinentes pour son appel * / collection.find (requête) .toArray (/ node-callback / (err, result) {if (err) {rejeter (err);} else {résoudre (résultat);}}); };

… ou si l’on cherche à résoudre le problème qui consiste à ne résoudre que le rappel spécifique à un nœud, est-il plus logique de disposer d’une forme de résolveur de promesse, afin d’éviter d’avoir à écrire / copier-coller une demi-douzaine lignes purement redondantes qui devraient être complètement séchées?

 // find = curry(query, collection) let resolver = new NodeResolver(); collection.find(query).toArray(promise.resolve); return resolver.promise; 

Oui, c’est un anti-modèle … … pourtant, un anti-modèle qui nécessite moins de frappes au clavier, restaure le stream naturel de la chaîne de promesses, corrige un problème avec l’API de rappel uniquement de Node, réduit le risque d’erreur, et cetera.

Oui, il existe déjà des bibliothèques qui le font … … des solutions spécifiques à la bibliothèque X ou à Y … … ou des solutions qui annulent globalement les méthodes de divers modules (effrayant) … ou des solutions qui, encore une fois, vous oblige à transmettre tous les détails de l’appel que vous effectuez:

 wrapNodeMethod(fs, "read", url, config).then(data => { /*...*/ }); 

Mais il n’existe pas de solution simple au cas de l’inversion de toute cette douleur sans:

a) envelopper le corps entier de la fonction dans une promesse, pour alimenter le résolveur asynchrone avec un résolveur b) en utilisant un anti-modèle dans une bibliothèque, afin de transmettre aux rappels de nœuds un résolveur dont le rest du corps de la fonction n’a besoin de rien savoir.

Même si les données devaient être transformées dans le résolveur, il serait plus logique de renvoyer un ensemble transformé dans une nouvelle promesse.

 let resolver = new NodeResolver(); somethingAsync(resolver.resolve); return resolver.promise.then(transformData).then(logTransform); 

… que pour envelopper tout le corps, y compris les transformations, etc., juste pour une référence de fermeture, juste pour éviter un “anti-modèle” qui va clairement à l’encontre de ce qui est devenu une plate-forme / un paradigme très répandu de JS.

Personnellement, je serais plus heureux si les méthodes de nœud IO || retournaient une promesse et / ou un stream, tout en prenant un rappel, en tant que partie essentielle de la plate-forme … … cela ne se produira pas. ..

… mais vous ne pouvez probablement pas me dire qu’écrire moins, et garder les modules Node secs, tout en utilisant ES6 Promises, est un “anti-modèle”, sans me fournir une solution plus eloquent.

Si vous pouvez, en effet, me fournir quelque chose que je peux utiliser dans tout rappel de NodeJS, ce qui en fait fournit une solution plus eloquent à ce problème, de sorte que je n’ai pas à encapsuler chaque corps de chaque méthode contenant un rappel asynchrone dans un nouveau constructeur, ou utilisez des méthodes de répartiteur maladroites, ou détourner des modules entiers pour écraser leurs fonctionnalités globales …

… je serais plus que disposé à retirer ma déclaration selon laquelle ce modèle particulier est toujours très utile, en ce qui concerne l’interface avec les API qui sont sujets aux pyramides o’dewm.

Si le résultat d’une promesse dépend d’une autre promesse, vous devez simplement créer une promesse en utilisant then .

Ce qui a été proposé par @Norguard sous forme directe n’a pas beaucoup de sens (c’est même inventé comme anti-modèle différé ). Le code ci-dessous fait exactement la même chose, et aucune promesse supplémentaire n’est requirejse:

 var deferredSomething = function () { return waitAWhile() .then(doStuff) .then(function (result) { if (result.isGood) { return result.data; } else { throw result.error; } }); }); }; 

Et, même si, pour une raison quelconque, vous auriez besoin de créer une promesse dès le départ, avec un modèle de constructeur, il serait plus simple de le faire ainsi:

 var deferredSomething = function () { return new Promise(function (resolve, reject) { waitAWhile() .then(doStuff) .then(function (result) { if (result.isGood) { resolve(result.data); } else { reject(result.error); } }); }); };