J'ai une promesse qui renvoie des données et je veux l'enregistrer dans des variables. Est-ce impossible en JavaScript en raison de la nature asynchrone et dois-je utiliser onResolve
comme rappel?
Puis-je utiliser cela en quelque sorte (par exemple, envelopper avec async/wait):
const { foo, bar } = Promise.then(result => result.data, errorHandler);
// rest of script
au lieu de ça?
Promise.then(result => {
const { foo, bar } = result.data;
// rest of script
}, errorHandler);
Remarque: la bibliothèque Bluebird est utilisée à la place de l'implémentation native, et je ne peux pas passer de Promise à asnyc/wait ou Generators.
NON, vous ne pouvez pas obtenir les données de manière synchrone d'une promesse comme vous le suggérez dans votre exemple. Les données doivent être utilisées dans une fonction de rappel. Alternativement, dans le style de programmation fonctionnelle, les données de promesse pourraient être map () ed over .
Si vous êtes d'accord en utilisant async/wait (vous devriez que ce soit génial), vous pouvez écrire du code qui semble synchrone tout en conservant l'asynchronicité d'une promesse (voir les commentaires @loganfsmyth).
const { foo, bar } = await iAmAPromise.then(result => result.data);
Dans l'ensemble, puisque vous utilisez déjà ES6, je suppose que vous utilisez également un transpilateur. Dans ce cas, vous devez absolument essayer asynchrone/attendre un essai. Assurez-vous simplement de peser dans la décision que, comme aujourd'hui, ils ne sont pas encore une spécification ratifiée.
Bien que vous puissiez obtenir une valeur d'une promesse attendue à l'intérieur d'une fonction asynchrone (simplement parce qu'elle suspend la fonction pour attendre un résultat), vous ne pouvez jamais obtenir une valeur directement d'une promesse et la remettre dans la même portée que la promesse elle-même .
C'est parce que "hors" signifierait essayer de prendre quelque chose qui existe dans le futur (la valeur finalement résolue) et le mettre dans un contexte (affectation de variable synchrone) qui s'est déjà produit dans le passé .
C'est-à-dire un voyage dans le temps. Et même si le voyage dans le temps était possible, ce ne serait probablement pas une bonne pratique de codage car le voyage dans le temps peut être très déroutant. :)
En général, si vous vous sentez comme vous devez le faire, c'est bon signe que vous devez refactoriser quelque chose. Notez que ce que vous faites avec "result => result.data" ici:
Promise.then(result => result.data, errorHandler);
// rest of script
..is déjà un cas où vous travaillez avec (littéralement, mappant) la valeur en la passant à une fonction. Mais, en supposant que "// reste du script" fasse quelque chose d'important lié à cette valeur, vous voudrez probablement continuer le mappage sur la valeur maintenant mise à jour avec encore une autre fonction qui fait alors quelque chose d'effet secondaire-y avec la valeur (comme afficher les données à l'écran).
Promise
.then(result => result.data)
.then(data => doSomethingWithData)// rest of script
.catch(errorHandler);
"doSomethingWithData" sera appelé ( si il est déjà appelé) à un moment inconnu dans le futur. C'est pourquoi il est recommandé d'encapsuler clairement tout ce comportement dans une fonction spécifique, puis de connecter cette fonction à la chaîne Promise.
C'est honnêtement mieux de cette façon, car cela vous oblige à déclarer clairement une séquence particulière d'événements qui se produira , explicitement séparée de la première exécution à travers tous l'exécution de votre code d'application.
En d'autres termes, imaginez ce scénario, exécuté hypothétiquement dans la portée globale de niveau supérieur:
const { foo, bar } = Promise.then(result => result.data, errorHandler);
console.log(foo);
//...more program
À quoi vous attendriez-vous? Il y a deux possibilités, et les deux sont mauvaises.