J'essaie de passer un appel API et je souhaite qu'il se répète toutes les 2 secondes. Cependant, je crains que si le système ne reçoive pas une demande dans les 2 secondes, il construira des demandes et continuera d'essayer de les envoyer. Comment puis-je éviter cela?
Voici l'action que j'essaie de fetch
:
function ping() { setInterval( getMachineAction(), 2000 ); }
Et puis je l'appelle avec un setInterval
.
const getMachineAction = async () => { try { const response = await fetch( 'https://localhost:55620/api/machine/'); if (response.status === 200) { console.log("Machine successfully found."); const myJson = await response.json(); //extract JSON from the http response console.log(myJson); } else { console.log("not a 200"); } } catch (err) { // catches errors both in fetch and response.json console.log(err); } };
J'ai pensé à faire une promesse comme une structure dans le setInterval pour m'assurer que la récupération avait fonctionné et terminé, mais n'a pas pu obtenir ça marche.
3 Réponses :
Simple! Stockez simplement s'il fait actuellement une requête et stockez si le minuteur s'est déclenché sans envoyer de nouvelle requête.
setInterval(getMachineAction, 2000);
Pour démarrer l'intervalle, vous devez omettre le () code>:
let in_progress = false; let missed_request = false; const getMachineAction = async () => { if (in_progress) { missed_request = true; return; } in_progress = true; try { const response = await fetch('https://localhost:55620/api/machine/'); if (missed_request) { missed_request = false; setTimeout(getMachineAction, 0); } if (response.status === 200) { console.log("Machine successfully found."); const myJson = await response.json(); //extract JSON from the http response console.log(myJson); } else { console.log("not a 200"); } } catch (err) { // catches errors both in fetch and response.json console.log(err); } finally { in_progress = false; } };
Salut @ wizzwizz4, cela fonctionnerait probablement si j'étais d'accord pour ignorer les demandes (c'est-à-dire exécuter à 2,4,8,10 et qu'il en avait ignoré 6), mais je veux que cela fonctionne comme s'il s'exécutait dès que possible, puis 2 secondes après que (c'est-à-dire exécuter à 2,4,7,9,10 où le 6 a pris une seconde supplémentaire donc maintenant ses 2 secondes après). De plus, je pense que vous devez définir votre variable in_progress
sur true dans la première ligne après try
, n'est-ce pas? Merci d'avoir pris le temps de répondre!
@thalacker Oui, je le fais. (Ou la première ligne avant, ce qui fonctionne.) Et cela devrait faire 2, 4, 6,3, 8, 10 si celui qui commence sur 4 prend 2,3 secondes, contrairement à la solution de charlietfi. La solution Promise.all
est soignée, mais semble fonctionner presque de la même manière que la solution de chatlietfi (2, 4, 6.3, 8.3, 10.3). Quelle fonctionnalité recherchiez-vous?
Vous pouvez ajouter un enfin
à votre try / catch
avec un setTimeout
au lieu d'utiliser votre setInterval
.
Notez qu'une longue interrogation comme celle-ci crée beaucoup plus de charge sur le serveur que l'utilisation de websockets qui sont eux-mêmes beaucoup plus en temps réel
const getMachineAction = async () => { try { const response = await fetch( 'https://localhost:55620/api/machine/'); if (response.status === 200) { console.log("Machine successfully found."); const myJson = await response.json(); //extract JSON from the http response console.log(myJson); } else { console.log("not a 200"); } } catch (err) { // catches errors both in fetch and response.json console.log(err); } finally { // do it again in 2 seconds setTimeout(getMachineAction , 2000); } }; getMachineAction()
Notez que cela se produit 2000 secondes après la fin de la requête, et non 2000 secondes après le démarrage de la requête.
@charlietfl avez-vous une ressource Websockets que vous recommanderiez de consulter ou de lire?
Quelle langue utilisez-vous dans le back-end? Effectuez simplement une recherche sur les Websockets
@charlietfl J'exécute une API Web C # .NET Core. Je peux rechercher des sockets Web C #. Se connecter principalement via des appareils externes pour collecter des données
La solution Promise.all ()
Cette solution garantit que vous ne manquez pas l'exigence de délai de 2 secondes ET que vous ne déclenchez pas non plus un appel lorsqu'un autre appel réseau est en cours.
function callme(){ //This promise will resolve when the network call succeeds //Feel free to make a REST fetch using promises and assign it to networkPromise var networkPromise = fetch('https://jsonplaceholder.typicode.com/todos/1'); //This promise will resolve when 2 seconds have passed var timeOutPromise = new Promise(function(resolve, reject) { // 2 Second delay setTimeout(resolve, 2000, 'Timeout Done'); }); Promise.all( [networkPromise, timeOutPromise]).then(function(values) { console.log("Atleast 2 secs + TTL (Network/server)"); //Repeat callme(); }); } callme();Remarque: Cela prend en charge la définition de la mauvaise casse comme demandé par l'auteur de la question:
"le" mauvais cas "(c'est-à-dire que cela prend plus de 2 secondes ) est que je veux qu'il ignore cette demande, puis en envoie une nouvelle. Donc, à 0 seconde, la demande est envoyée. Cela prend 3 secondes pour s'exécuter, puis 2 secondes plus tard (à 5), il devrait réexécuter. Donc, il étend simplement le jusqu'à ce qu'il envoie. "
On dirait que cela fonctionnerait très bien. La fonction callme ()
ou la networkPromise
serait-elle mon getMachineAction
?
networkPromise sera getMachineAction - callme n'est qu'un wrapper !! Bonne chance avec votre codage
Je vois ça maintenant. Ugh, erreur stupide. Merci!
Toutes les 2 secondes sont-elles une exigence exacte? Sinon, ne le faites pas toutes les 2 secondes. Utilisez
setTimeout
et planifiez les 2 secondes suivantes après la fin des précédentes.Il y aura un temps défini, que ce soit 2 secondes ou 30 secondes dépendra d'une variable, mais il restera cohérent. (donc s'il est réglé sur toutes les 2 secondes, cela doit se produire toutes les 2 secondes)
Peut-être regardez dans étranglement / débouncing - j'oublie lequel est lequel. lodash a les deux méthodes.
Que voulez-vous qu'il advienne de la demande précédente à 2 secondes? Doit-il annuler? Quelle est votre exigence relative au «mauvais cas»?
@ zero298 le "mauvais cas" (c'est-à-dire que cela prend plus de 2 secondes) est que je veux qu'il ignore cette demande, puis en envoie une seule nouvelle. Donc à 0 seconde, la demande est envoyée. Il faut 3 secondes pour s'exécuter, puis 2 secondes plus tard (à 5), il devrait être réexécuté. Donc, cela prolonge simplement le temps jusqu'à ce qu'il envoie.
@Andy Ni l'un ni l'autre n'aidera ici
@Bergi, je suis d'accord. Avez-vous des recommandations? J'ai tendance à penser que la réponse de charlietfl est la voie à suivre.
L'approche de @thalacker takrishna est la voie à suivre. Voir également ici