Modèle d'enveloppement d'une fonction JavaScript asynchrone pour le rendre synchrone

Je travaille avec une API JavaScript où la plupart des fonctions sont asynchrones. L'API est l' API de base de données JavaScript WebKit qui est une liaison à un sous-ensemble de fonctionnalités pour manipuler les bases de données SQLite3. Je comprends la décision de conception pour rendre les choses asynchiques pour ne pas bloquer et fournir une interface utilisateur réactive. Dans ma situation, je sais que mon utilisation des appels de l'API asynchique s'exécutera rapidement. Comme c'est le cas, je souhaite offrir à mes développeurs une API wrapper plus propre et plus facile à utiliser qui oblige les appels synchrones.

Voici l'appel asynchrone

db.executeSql(sqlStatement, function(result) { // do something with result }); 

Et voici ce que j'aimerais pouvoir faire

 var result = dbWrapper.executeSql(sqlStatement); // do something with result 

Existe-t-il un modèle de conception / façon de le faire? Un exemple écrit ou lié à un code est préféré. La plate-forme cible / broswer est Mobile Safari sur l'iPhone.

Je vous remercie

Désolé, JavaScript ne fournit pas les primitives de la langue (p. Ex. Threads ou coroutines) pour que les choses asynchrones fonctionnent de manière synchrone ou vice versa.

Vous n'utilisez généralement qu'un seul thread d'exécution, donc vous ne pouvez pas obtenir un rappel à partir d'une minuterie ou XMLHttpRequest readystatechange jusqu'à ce que la pile d'appels menant à la création de la requête soit complètement démêlée.

En bref, vous ne pouvez pas vraiment le faire; L'approche avec fermetures imbriquées sur la page WebKit que vous avez associée est la seule façon dont je sais que le code est lisible dans cette situation.

*: Sauf dans certaines situations obscures qui ne vous aideront pas et sont généralement considérés comme des bugs

StratifiedJS vous permet de faire exactement cela.

Il y a même un article sur la façon de l'appliquer sur le stockage du navigateur: http://onilabs.com/blog/stratifying-asynchronous-storage

Et c'est la bibliothèque de JavaScript stratifié qu'il utilise https://gist.github.com/613526

L'exemple se présente comme suit:

 var db = require("webdatabase").openDatabase("CandyDB", ...); try { var kids = db.executeSql("SELECT * FROM kids").rows; db.executeSql("INSERT INTO kids (name) VALUES (:name);", [kids[0]]); alert("done"); } catch(e) { alert("something went wrong"); } 

Peut-être un peu en retard, mais la technologie n'existait pas à l'époque;)

Vous pouvez essayer quelque chose comme:

 function synch() { var done = false; var returnVal = undefined; // asynch takes a callback method // that is called when done asynch(function(data) { returnVal = data; done = true; }); while (done == false) {}; return returnVal; } 

Mais cela peut geler votre navigateur pour la durée de la méthode Asynch …

Ou jeter un oeil à Narrative JavaScript: Narrative JavaScript est une petite extension de la langue JavaScript qui permet de bloquer les capacités pour les rappels d'événements asynchrones. Cela rend le code asynchrone lisible et compréhensible.

http://neilmix.com/narrativejs/doc/index.html

Mike

Si vous utilisez jQuery Ajax: $ .ajax ()

Vous pouvez définir l'attribut d'asynch sur false, puis vous aurez une demande de synchronisation ajax sur le serveur.

Nous utilisons GWT RPC qui possède également une API asynchrone. La solution que nous utilisons actuellement pour effectuer plusieurs appels asynchrones en série est le chaînage d'appel:

 callA(function(resultA) { callB(resultA, function(resultB) { callC(); //etc. }); }); 

Cette approche imbriquée réalise ce que vous voulez, mais il est révélateur et difficile à lire pour les nouveaux arrivants. Une des approches que nous avons étudiées est d'ajouter les appels que nous devons faire à une pile et de les exécuter dans l'ordre:

 callStack = [ callA(), callB(), callC() ]; callStack.execute(); 

Ensuite, le callstack gérerait:

  1. En appelant les appels en série (c.-à-d. Le câblage dans le premier exemple)
  2. Passer le résultat d'un appel à l'étape suivante.

Cependant, comme Java n'a pas de références de fonction, chaque appel sur la pile d'appel nécessiterait une classe anonyme, de sorte que nous nous sommes arrêté à une telle solution. Cependant, vous pouvez avoir plus de succès dans javascript.

Bonne chance!

Cela n'employe pas le fonctionnement synchrone de la requête db, mais c'était ma solution pour une gestion facile. Utilisez essentiellement la fonction d'appel comme fonction de rappel et testez l'argument de résultat. Si la fonction reçoit des résultats, elle les analyse, sinon, elle se transmet comme rappel à la méthode de requête.

  render: function(queryResults){ if (typeof queryResults != 'undefined'){ console.log('Query completed!'); //do what you will with the results (check for query errors here) } else { console.log('Beginning query...'); this.db.read(this.render); //db.read is my wrapper method for the sql db, and I'm sending this render method as the callback. } } 

Je ne sais pas si c'est le bon endroit, mais je suis ici pour chercher des réponses pour faire des appels synchrones dans Firefox. La solution consisterait à supprimer le rappel en ligne et à effectuer un appel direct. C'est ce que j'ai trouvé et ma solution répondait en mode synchrone avec un service de repos