2010-09-09 37 views
2

Je dois demander des données pour un script JS à partir d'une base de données MySQL (basée sur un identifiant utilisateur).Comment implémenter une fonction getter (en utilisant des callbacks)

Je n'ai pas trouvé de solution simple pour JavaScript et il n'a pas été possible de charger les données en utilisant ajax, car la base de données est disponible sous un domaine différent. J'ai implémenté une solution de contournement en utilisant PHP et curl.
Maintenant, le JS doit "attendre" que la requête se termine, mais le script est bien sûr exécuté de manière asynchrone et n'attend pas la réponse.
Je sais que ce n'est pas vraiment possible d'attendre en JS, mais il doit être possible de retourner une valeur comme ça.

J'ai également essayé d'utiliser un return comme un autre rappel, mais cela n'a pas fonctionné bien sûr, car la fonction getter fonctionnera quand même de toute façon.

Comment puis-je implémenter un getter simple, qui "attend" et renvoie la réponse de la requête HTTP?

Merci pour les autres indices. Je suis vraiment perdu en ce moment.
C'est un extrait du code source:

/** 
* Simple getter which requests external data 
*/ 
function simple_getter() { 

    // http request using a php script, because ajax won't work crossdomain 
    // this request takes some time. function finished before request is done. 

    /* Example */ 
    var url = "http://example-url.com/get_data.php?uid=1234"; 
    var response_callback = handle_result_response; 

    var value = send_request(url, response_callback); 

    value = value.split('*')[0]; 

    if (value === '' || value == const_pref_none) { 
     return false; 
    } 

    /* 1. returns undefinied, because value is not yet set. 
     2. this as a callback makes no sense, because this function 
      will run asynchronous anyway. */ 
    return value; 
} 

Informations complémentaires sur les fonctions utilisées:

/** 
* Callback for the send_request function. 
* basically returns only the responseText (string) 
*/ 
function handle_result_response(req) { 
    // do something more, but basically: 
    return req.responseText; 
} 

/** 
* Requests data from a database (different domain) via a PHP script 
*/ 
function send_request(url, response_callback) { 
    var req = createXMLHTTPObject(); 

    if (!req) 
     return; 

    var method = (postData) ? "POST" : "GET"; 

    req.open(method, url, true); 
    req.setRequestHeader('User-Agent','XMLHTTP/1.0'); 

    // More not relevant source code 
    // ... 

    req.onreadystatechange = function() { 
     // More not relevant source code 
     // ... 

     response_callback(req); 
    } 

    if (req.readyState == 4) 
     return; 

    req.send(postData); 

} 

Pas vraiment code approprié, mais nécessaire pour le HTTP demande:

var XMLHttpFactories = [ 
    function() {return new XMLHttpRequest()}, 
    function() {return new ActiveXObject("Msxml2.XMLHTTP")}, 
    function() {return new ActiveXObject("Msxml3.XMLHTTP")}, 
    function() {return new ActiveXObject("Microsoft.XMLHTTP")} 
]; 


function createXMLHTTPObject() { 
    var xmlhttp = false; 

    for (var i=0; i<XMLHttpFactories.length; i++) { 

     try { 
      xmlhttp = XMLHttpFactories[i](); 
     } catch (e) { 
      continue; 
     } 

     break; 
    } 

    return xmlhttp; 
} 

Répondre

3

Vous ne devriez vraiment pas essayer d'attendre de manière synchrone qu'une requête réseau soit terminée. Il se peut que la requête ne soit jamais terminée, qu'elle puisse être suspendue et prendre beaucoup de temps, et ainsi de suite. Comme JavaScript est un thread unique, et en fait tous les principaux moteurs de navigation sont mono-thread, cela entraînera le blocage de l'ensemble de votre page en attente de la requête, et dans certains navigateurs, le navigateur entier risque de se bloquer.

Ce que vous devez faire est de remplacer le code comme ceci:

var returned = some_request('http://example.com/query'); 
do_something_with(returned); 

avec le code comme ceci:

some_request('http://example.com/query', function (returned) { 
    do_something_with(returned); 
}); 

De cette façon, vous ne serez jamais faire votre page ou le navigateur pour suspendre en attendant le demande, et peut simplement faire le travail une fois que la réponse entre en jeu.

0

Je ne vois pas ce qui ne va pas avec votre code en général.

Lorsque vous effectuez une requête, fournissez un rappel. Quand une réponse revient, que vous pouvez facilement détecter, exécutez le rappel et transmettez le résultat.

0

C'est ainsi que fonctionnent les applications côté client.
Ce n'est pas une procédure, mais cela fonctionne par événements.

  1. vous présente l'écran pour l'utilisateur et attendre
  2. L'utilisateur effectue une action
  3. Vous appelez le serveur, définissez un rappel et attendre
  4. La réponse vient et vous exécutez le rappel et attendre Pour une autre étape 2

Plutôt que d'essayer de changer cela, vous devez vous adapter à cela ou ce sera une expérience douloureuse.

Javascript n'est pas multithread. Cela signifie qu'une seule instruction est exécutée à la fois. L'asynchronisme réel vient du temps que prend le serveur pour répondre et appeler le rappel. Vous ne savez jamais quel appel va venir en premier et devez construire votre programme en ayant cela à l'esprit.