Comment créer une fonction qui renvoie une promesse existante plutôt qu'une nouvelle promesse?

JavaScript / Promesse des experts,

J'espère que vous pouvez m'aider parce que je ne comprends pas comment je peux créer une fonction qui renvoie une promesse existante au lieu d'une nouvelle promesse. J'ai fait beaucoup de recherches, mais tous les exemples renvoient une nouvelle promesse chaque fois que la fonction est appelée.

Supposons que j'ai une fonction qui prend du temps pour traiter et générer un résultat différent chaque fois qu'il s'appelle. Lorsque j'utilise la méthode de la nouvelle promesse, je dois toujours attendre pour la compléter à chaque fois et je n'obtiens pas la même valeur si je rappelle la fonction.

J'ai inclus une preuve de concept que j'ai créée qui fonctionne comme souhaité (sauf si j'ai oublié quelque chose). Je pense que cette «solution» est moche, car j'ai besoin de déplacer des variables à une portée plus grande et j'ai encore besoin de créer une nouvelle promesse à chaque fois que la fonction est appelée.

Mon hypothèse en ce moment; Pour créer ce code intéressant, la fonction doit renvoyer une promesse existante au lieu d'une nouvelle, mais si d'autres solutions offrent la même fonctionnalité et un code plus agréable, laissez-moi savoir. L'ES6 natif est préféré.

Merci!

'use strict'; var p; var q; var randomNumber = function() { return new Promise(function(resolve) { console.log(`p: ${p}`); if (typeof p === 'undefined') { setTimeout(function() { p = Math.random(); resolve(p); }, 1000); } else { resolve(p); } }); }; var randomNumberPlusOne = function() { return new Promise(function(resolve) { console.log(`q: ${q}`); if (typeof q === 'undefined') { randomNumber() .then(function(p) { q = p + 1; resolve(q); }); } else { resolve(q); } }); }; var showResult = function(result) { console.log(); console.log(`r: ${result}`); }; randomNumber() .then(showResult); randomNumber() .then(randomNumberPlusOne) .then(showResult); randomNumberPlusOne() .then(showResult); setTimeout(function() { console.log(); console.log('setTimeout:'); console.log(); randomNumber() .then(showResult); randomNumber() .then(randomNumberPlusOne) .then(showResult); randomNumberPlusOne() .then(showResult); }, 2000); 

– (le code ci-dessous est basé sur les commentaires de Bergi;

 'use strict'; var randomNumber = (function() { var p = null; return function() { console.log('p:'); console.log(p); console.log(); if (!p) { p = new Promise(function(resolve) { setTimeout(function() { resolve(Math.random()); }, 1000); }); } return p; }; })(); var randomNumberPlusOne = (function() { var q = null; return function() { console.log('q:'); console.log(q); console.log(); if (!q) { q = randomNumber() .then(function(p) { return p + 1; }); } return q; }; })(); var showResult = function(result) { console.log(`r: ${result}`); console.log(); }; randomNumber() .then(showResult); randomNumber() .then(randomNumberPlusOne) .then(showResult); randomNumberPlusOne() .then(showResult); setTimeout(function() { console.log(); console.log('setTimeout:'); console.log(); randomNumber() .then(showResult); randomNumber() .then(randomNumberPlusOne) .then(showResult); randomNumberPlusOne() .then(showResult); }, 2000); 

Vous voudrez memoise la promesse , pas la valeur qu'il résout avec. Le mémoires fonctionne bien avec des promesses en tant que valeurs de résultat.

 var p = null; function notSoRandomAsyncNumber() { if (!p) p = new Promise(function(resolve) { setTimeout(function() { resolve(Math.random()); }, 1000); }); return p; } 

Ou, abstraite dans une fonction helper:

 function memoize(fn) { var cache = null; return function memoized(args) { if (fn) { cache = fn.apply(this, arguments); fn = null; } return cache; }; } function randomAsyncNumber() { return new Promise(res => { setTimeout(() => resolve(Math.random()), 1000); }); } function randomAsyncNumberPlusOne() { return randomAsyncNumber().then(n => n+1); } var notSoRandomAsyncNumber = memoize(randomAsyncNumber); var notSoRandomAsyncNumberPlusOne = memoize(randomAsyncNumberPlusOne); 

(Notez que notSoRandomAsyncNumberPlusOne va encore créer un randomAsyncNumber() sur le premier appel, et non un notSoRandomAsyncNumber() )

Essayez la nouvelle approche variable proposée. Les promesses sont conçues pour être simples, donc cela dépend de la mise en œuvre. Ce que vous essayez de faire est plus dans l'arène des événements ou reactivex. Si vous utilisez jquery, vous pouvez utiliser leur système d'événements. Un plus propre est disponible sur le site nodejs. Comme il ne nécessite rien d'autre, il fonctionne dans le navigateur. Rxjs est la crème de la culture de traitement des flux, mais c'est une grande bibliothèque et nécessite un certain apprentissage. Cela vaut le coup, car la même connaissance est un client et un serveur utiles dans de nombreuses langues. Vous pouvez même configurer un flux à partir d'une promesse – parmi beaucoup d'autres façons.