Je sais que c'est une idée terrible. Mais j'ai une API que je ne peux pas utiliser tant que je n'ai pas une donnée que je ne peux obtenir que de manière asynchrone. Quelque chose comme ceci:
import API from '@/api' const key = async get_key() // NOPE const theAPI = new API(key) async importantMethod(args) { return await theAPI.f1(args) } async otherMethod() { if (theAPI.f3) return await theAPI.f2(123) // etc... } // ... and so on
C'est au plus haut niveau, en dehors de toute fonction, donc je ne peux pas simplement attendre get_async_data () (il renvoie une promesse). Y a-t-il quelque chose à part de mettre tout mon code dans une fonction asynchrone géante pour que je puisse appeler await?
API
est juste une classe exportée par un module (que je contrôle).
(BTW, j'ai pensé à mettre le code pour obtenir la clé dans le constructeur de la classe API
, mais bien sûr, les constructeurs ne peuvent pas non plus être asynchrones.)
Je pourrais faire en sorte que chaque méthode asynchrone de l ' API
définisse la clé si elle n'est pas définie, mais c'est assez invasif et sujet aux erreurs.
Donc, je ne demande pas vraiment comment faire mon top- le code de niveau attendez autant que je cherche des moyens alternatifs de structurer cela pour que l'appel async se passe proprement.
Voici quelques détails supplémentaires au cas où cela aiderait. Dans api.js:
class API { constructor(key) { this.key = key // other stuff } async f1(a) { } async f2(b, c) { } f3() { return true } } export default API
Puis aux endroits (nombreux) où il sera utilisé:
const key = await get_async_data(config) // NOT RIGHT, can't use await at top level const api = new API(key) ... use api ...
3 Réponses :
Le niveau supérieur est une idée terrible, oui. Mais je ne vois pas pourquoi vous ne pouvez pas simplement le mettre dans une fonction?
const getAsync = async () => { const key = await get_async_data(config); return key; } getAsync().then(key => { const api = new API(key) }
Pas besoin de wait
/ async
si vous utilisez .then
, faites simplement get_async_data (config) .then (key =>
De plus, ce n'est pas tant une "mauvaise idée" (ce n'est pas une mauvaise idée, il y a actuellement une proposition pour await
de niveau supérieur) qu'une idée qui n'est actuellement pas autorisée par la spécification.
bien sûr, mais il semble vouloir une fonction plus petite disponible pour une utilisation ailleurs. Peut-être pour impliquer d'autres paramètres? et que ce soit juste une pure promesse ou écrit comme une attente asynchrone n'est ni ici ni là.
re proposition, je ne savais pas ça, intéressant. Je dirais toujours que faire des fonctionnalités dans le monde entier est généralement à éviter, mais je comprends qu'il existe d'autres points de vue à ce sujet. J'imagine que le niveau supérieur attendre le ferait sentir un peu plus PHP / Python-y.
Le niveau supérieur d'un projet ne signifie pas nécessairement global, heureusement - c'est à cela que servent les bundleurs de modules.
vrai, mais semble toujours être une manière inutilement obtuse de faire les choses.
Utilisez simplement la promesse:
import pendingAPI from 'other/file'; pendingAPI.then(doStuffWithAPI);
En attendant, dans un autre fichier ...
const pendingAPI = get_async_data(config).then(key => new API(key)); // N.B. no await export default pendingAPI;
Il y a des moments où asynchrone / wait
est une victoire. Mais n'oubliez jamais que c'est juste du sucre sur les promesses.
Si vous voulez modifier le moins possible votre code existant, j'envisagerais de changer le point d'entrée en un module qui récupère la clé, puis d'appeler le module qui instancie l'API (l'ancien point d'entrée). Par exemple:
// start.js import makeApi from './makeApi'; get_key() .then(makeApi); // makeApi.js export default function(key) { const theApi = new API(key); function importantMethod(args) { return theAPI.f1(args) } function otherMethod() { if (theAPI.f3) return theAPI.f2(123) } // etc }
En bref, tout ce que vous avez à faire est d'encapsuler votre point d'entrée actuel dans une fonction.
Pouvez-vous expliquer le problème que vous rencontrez avec l'encapsulation du code dans une fonction
async
(ou simplement en utilisant.then
)? Cela semble être la solution évidenteJe souhaite utiliser cette API partout, dans toutes mes classes. Je ne peux pas tout envelopper dans une fonction asynchrone géante.
Vous ne savez pas ce que vous voulez dire, mais vous devrez attendre cette fonction partout où vous devez attendre que la promesse se résout avant de continuer. Ou si vous ne voulez pas tout envelopper dans une fonction asynchrone, utilisez simplement .then à la place.
Pouvez-vous donner un exemple plus concret avec plus de code, afin que nous puissions voir ce qui vous semble trop compliqué? Ce n'est pas tout à fait clair ATM
Appelez simplement l'API, remplissez la promesse résultante dans un var et attendez si nécessaire.
@JaredSmith avec les détails supplémentaires que j'ai ajoutés, pouvez-vous expliquer comment cela fonctionnerait dans mon cas?