Chiamata Asincrona Funzione Javascript In Modo Sincrono

Prima, questo è un caso molto specifico di farlo nel modo sbagliato su di scopo per il retrofit di una chiamata asincrona in un sincrono codebase è che molte migliaia di linee lungo tempo e attualmente non permettersi la possibilità di apportare le modifiche al “fare bene.” Mi fa male ogni fibra del mio essere, ma la realtà e ideali spesso non maglia. So che questo fa schifo.

OK, che fuori del modo, come faccio a fare in modo che ho potuto:

function doSomething() {

  var data;

  function callBack(d) {
    data = d;
  }

  myAsynchronousCall(param1, callBack);

  //block here and return data when the callback is finished
  return data;
}

Esempi (o mancanza di esso), in tutte le librerie e/o compilatori, entrambi i quali non sono vitali per questa soluzione. Ho bisogno di un esempio concreto di come fare blocco (ad esempio, per NON lasciare il doSomething funzione fino a quando la callback viene chiamata) SENZA congelamento dell’interfaccia utente. Se una cosa del genere è possibile in JS.

Semplicemente non è possibile fare un browser di blocco e di attendere. Essi semplicemente non farlo.
javascript dosent avendo meccanismo di blocco sulla maggior parte dei browser…dovrai creare un callback che viene chiamato quando la chiamata asincrona finiture per restituire i dati
Non credo che questo possa essere fatto. Javascript (web lavoratori in deroga) è singolo a thread – che la richiamata non può essere chiamato fino a che l’attuale gestore di eventi restituisce. Questo richiederebbe l’equivalente di C# async/await funzione in Javascript e dubito che una bestia esiste. Ho paura che sei bloccato riscrivere il codice in CPS, come fastidioso come è.
Hai chiesto un modo per dire al browser “so che vi ho appena detto che per eseguire tale funzione precedente in modo asincrono, ma non mi dire!”. Perché ancora aspetta che sia possibile?
Grazie Dan per la modifica. Io non strettamente essere scortese, ma il testo è di meglio.

OriginaleL’autore Robert C. Barth | 2012-02-03

5 Replies
  1. 106

    “non dirmi come devo solo fare il “modo giusto” o quello”

    OK. ma si dovrebbe davvero fare le cose nel modo giusto… o qualsiasi

    ” Ho bisogno di un esempio concreto di come farlo bloccare … SENZA il congelamento dell’interfaccia utente. Se una cosa del genere è possibile in JS.”

    No, è impossibile bloccare l’esecuzione di JavaScript senza bloccare l’interfaccia utente.

    Data la mancanza di informazioni, è difficile offrire una soluzione, ma una possibilità potrebbe essere quella di avere la funzione di chiamata di fare qualche polling per controllare una variabile globale, hanno la funzione di callback set data globale.

    function doSomething() {
    
          //callback sets the received data to a global var
      function callBack(d) {
          window.data = d;
      }
          //start the async
      myAsynchronousCall(param1, callBack);
    
    }
    
      //start the function
    doSomething();
    
      //make sure the global is clear
    window.data = null
    
      //start polling at an interval until the data is found at the global
    var intvl = setInterval(function() {
        if (window.data) { 
            clearInterval(intvl);
            console.log(data);
        }
    }, 100);

    Tutto questo presuppone che si può modificare doSomething(). Non so se nelle carte.

    Se può essere modificato, quindi non so perché non solo passare un callback per doSomething() di essere chiamato da altri richiamata, ma ho di meglio fermarsi prima di entrare in difficoltà. 😉


    Oh, che diamine. Hai dato un esempio che suggerisce che può essere fatto correttamente, così ho intenzione di mostrare che la soluzione…

    function doSomething( func ) {
    
      function callBack(d) {
        func( d );
      }
    
      myAsynchronousCall(param1, callBack);
    
    }
    
    doSomething(function(data) {
        console.log(data);
    });

    Perché il vostro esempio, include una funzione di callback che viene passato per la chiamata asincrona, il modo giusto sarebbe quello di passare una funzione di doSomething() per essere richiamato dal richiamata.

    Naturalmente, se quella è l’unica cosa che la richiamata sta facendo, devi solo passare func direttamente…

    myAsynchronousCall(param1, func);
    Sì, so come farlo correttamente, ho bisogno di sapere come/se può essere fatto in modo non corretto per il motivo specifico dichiarato. Il punto cruciale è che non voglio lasciare doSomething() fino a quando myAsynchronousCall completa la chiamata alla funzione di callback. Bleh, non può essere fatto, come sospettavo, ho solo bisogno di raccolto la saggezza di Internets a tornare in me. Grazie. 🙂
    Sì, i tuoi sospetti erano fondati, purtroppo.
    Sono io o solo il “fatto correttamente” versione lavoro? La questione inclusa una chiamata di ritorno, prima che ci dovrebbe qualcosa che attende la chiamata asincrona per finire, la prima parte di questa risposta non di copertura…
    La risposta afferma che non è possibile di fare ciò che vuole. Quella è la parte importante da capire. In altre parole, non è possibile effettuare una chiamata asincrona e restituire un valore senza bloccare l’interfaccia utente. Quindi la prima soluzione è un brutto hack utilizza una variabile globale e polling per vedere se la variabile è stata modificata. La seconda versione è il modo corretto.
    È la misteriosa funzione chiamata in questione. Fondamentalmente rappresenta tutto ciò che viene eseguito il codice in modo asincrono e produce un risultato che deve essere ricevuto. Quindi potrebbe essere come una richiesta AJAX. Si passa il callback funzione per la myAsynchronousCall funzione, che fa il suo async roba e richiama la funzione di callback. Qui c’è una demo.

    OriginaleL’autore

  2. 46

    Dare un’occhiata a JQuery Promesse:

    http://api.jquery.com/promise/

    http://api.jquery.com/jQuery.when/

    http://api.jquery.com/deferred.promise/

    Refactoring del codice:

     
    var dfd = new jQuery.Imposte differite (attive); 
    
    
    la funzione di callBack(data) { 
    dfd.notify(dati); 
    } 
    
    //esegue la chiamata asincrona. 
    myAsynchronousCall(param1, callBack); 
    
    funzione doSomething(data) { 
    //fai qualcosa con i dati... 
    } 
    
    $.quando(dfd).quindi(doSomething); 
    
    
    
    +1 per questa risposta, questo è corretto. tuttavia, vorrei aggiornare il linea con dfd.notify(data) per dfd.resolve(data)
    È questo un caso di codice che dà l’illusione di essere sincrono, senza in realtà NON essere asincrona ?
    le promesse sono IMO solo ben organizzato richiamate 🙂 se avete bisogno di una chiamata asincrona in diciamo un oggetto di inizializzazione, di promesse rende un po ‘ di differenza.
    Promesse non sono sincronizzati.
    Provare questo github.com/dineshkani24/queuecall

    OriginaleL’autore Matt Taylor

  3. 6

    C’è una bella soluzione alternativa a http://taskjs.org/

    Utilizza generatori che sono di nuovo a javascript. Quindi è attualmente implementato dalla maggior parte dei browser. L’ho provato in firefox, e per me è un bel modo per avvolgere funzione asincrona.

    Ecco un codice di esempio dal progetto GitHub

    var { Deferred } = task;
    
    spawn(function() {
        out.innerHTML = "reading...\n";
        try {
            var d = yield read("read.html");
            alert(d.responseText.length);
        } catch (e) {
            e.stack.split(/\n/).forEach(function(line) { console.log(line) });
            console.log("");
            out.innerHTML = "error: " + e;
        }
    
    });
    
    function read(url, method) {
        method = method || "GET";
        var xhr = new XMLHttpRequest();
        var deferred = new Deferred();
        xhr.onreadystatechange = function() {
            if (xhr.readyState === 4) {
                if (xhr.status >= 400) {
                    var e = new Error(xhr.statusText);
                    e.status = xhr.status;
                    deferred.reject(e);
                } else {
                    deferred.resolve({
                        responseText: xhr.responseText
                    });
                }
            }
        };
        xhr.open(method, url, true);
        xhr.send();
        return deferred.promise;
    }

    OriginaleL’autore George Vinokhodov

  4. 2

    L’idea che si spera di raggiungere può essere possibile, se si tweak la necessità di un po’

    Il codice di seguito è possibile se il runtime supporta l’ES6 specifica.

    Di più su async funzioni

    async function myAsynchronousCall(param1) {
        //logic for myAsynchronous call
        return d;
    }
    
    function doSomething() {
    
      var data = await myAsynchronousCall(param1); //'blocks' here until the async call is finished
      return data;
    }

    OriginaleL’autore eragon512

  5. 0

    È possibile utilizzare la ricorsione,
    basta creare una funzione che richiama se stessa,
    la chiamata a questa funzione 1 volta dal di fuori,
    all’interno della chiamata di funzione ricorsiva il codice asincrono,
    scorrere la vostra funzione ricorsiva mediante richiamate. ?

    OriginaleL’autore Thomas Gotwig

Lascia un commento