2014-04-24 13 views
8

Sto utilizzando una libreria jQuery chiamato bootboxQuali sono i C# in attesa equivalenti in javascript/jquery?

bootbox.dialog({ 
    title: "Group", 
    buttons: { 
     success: { 
      label: "OK", 
      className: "btn-success", 
      callback: function() { 
       postForm(); 
      } 
     } 
    } 
}); 

function postForm() {   
    $.ajax({ 
     type: "POST", 
     url: $("#add-group").val(), 
     data: $("#form").serialize(), 
     success: function (data) { 
      return true; 
     }, 
     error: function (XMLHttpRequest, textStatus, errorThrown) { 
      return false; 
     } 
    }); 
} 

Quando clicco sul pulsante "OK", a meno che non restituiscono un valore falso come questo:

callback: function() { 
    return false; 
} 

la finestra si chiude.

Nella funzione di richiamata, sto chiamando postForm che è una funzione che effettua una chiamata AJAX sul mio server per eseguire alcune operazioni. A seconda dell'esito di tale operazione, vorrei mantenere la finestra di dialogo ancora aperta.

Ma poiché si tratta di una chiamata AJAX e il risultato richiede un po 'di tempo per tornare indietro, la finestra di dialogo si chiude immediatamente dopo postForm() indipendentemente dal risultato.

Come posso dire a javascript di attendere il risultato della chiamata ajax?

Sarà grande se posso fare qualcosa di simile:

callback: function() { 
    var result = await postForm(); 
    return result; 
} 
+2

Javascript non è multithreaded, quindi, in attesa non è possibile. Esistono solo operazioni sincronizzate (in cui il codice viene eseguito in modo uniforme nel suo ordine) e operazioni asincrone, in cui l'operazione chiama le funzioni di callback dopo che è stata eseguita. Una soluzione alternativa è jquery promise(), che in realtà è un callback indiretto. – setec

+0

Quindi posso inserire postForm() in promise()? –

+0

Penso che si possa provare '$ .when' in' postForm() '. Non sono sicuro, ma dovrebbe funzionare –

risposta

6

Penso che Promises sia esattamente quello che stai chiedendo.

.promise()

restituire un oggetto promessa di osservare quando tutte le azioni di un certo tipo vincolato alla raccolta, in coda o meno, hanno finito. per esempio.

var div = $("<div>"); 

div.promise().done(function(arg1) { 
    // Will fire right away and alert "true" 
    alert(this === div && arg1 === div); 
}); 

Per maggiori informazioni consultare: https://api.jquery.com/promise/

promessa differita è più vicino al comportamento asincrona:

deferred.promise()

Il deferred.promise() metodo consente una funzione asincrona per impedire ad altri codici di interferire con lo stato di avanzamento o lo stato della sua richiesta interna. La promessa espone solo i metodi differite necessari per collegare i gestori aggiuntivi o determinare lo stato (then, done, fail, always, pipe, progress, e state), ma non quelli che modificano lo stato (resolve, reject, notify, resolveWith, rejectWith e notifyWith).

Se viene fornito un obiettivo, deferred.promise() allegherà i metodi su di esso e quindi restituirà questo oggetto anziché crearne uno nuovo. Questo può essere utile per collegare il comportamento di Promessa a un oggetto che esiste già.

Se si sta creando un rinviato, mantenere un riferimento al differito in modo che possa essere risolto o rifiutato a un certo punto. Restituire solo l'oggetto Promise tramite deferred.promise() in modo che altro codice possa registrare i callback o ispezionare lo stato corrente.

Esempio:

function asyncEvent() { 
    var dfd = new jQuery.Deferred(); 

    // Resolve after a random interval 
    setTimeout(function() { 
    dfd.resolve("hurray"); 
    }, Math.floor(400 + Math.random() * 2000)); 

    // Reject after a random interval 
    setTimeout(function() { 
    dfd.reject("sorry"); 
    }, Math.floor(400 + Math.random() * 2000)); 

    // Show a "working..." message every half-second 
    setTimeout(function working() { 
    if (dfd.state() === "pending") { 
     dfd.notify("working... "); 
     setTimeout(working, 500); 
    } 
    }, 1); 

    // Return the Promise so caller can't change the Deferred 
    return dfd.promise(); 
} 

// Attach a done, fail, and progress handler for the asyncEvent 
$.when(asyncEvent()).then(
    function(status) { 
    alert(status + ", things are going well"); 
    }, 
    function(status) { 
    alert(status + ", you fail this time"); 
    }, 
    function(status) { 
    $("body").append(status); 
    } 
); 

Per ulteriori informazioni, consultare la documentazione per oggetto differite: http://api.jquery.com/category/deferred-object/

jQuery.when()

Fornisce un modo per eseguire le funzioni di callback sulla base di uno o più oggetti, di solito oggetti rinviati che rappresentano eventi asincroni. Esempio:

$.when($.ajax("test.aspx")).then(function(data, textStatus, jqXHR) { 
    alert(jqXHR.status); // Alerts 200 
}); 
+0

Puoi estendere la tua risposta per riflettere come sarà il mio scenario? –

+0

Non sono sicuro di 'bootbox', sembra che fare clic su OK abbia un'azione predefinita per nascondere la finestra di dialogo in quella libreria. Nella finestra di dialogo semplice, ho fatto la stessa cosa nascondendo la finestra di dialogo solo a condizione. –

+0

se restituisco falso nella richiamata, non restituirà chiudi la finestra di dialogo –

4

Non è possibile. Non esiste un equivalente di await in JS.

Dovrete simularlo restituendo false all'invocazione di postForm e quindi dopo l'esecuzione della funzione di richiamata dalla chiamata AJAX chiudere la finestra di dialogo.

+2

Penso che possiamo simulare l'equivalente di quello usando 'promise' in jQuery. –

+0

Sì, sembra possibile, ed è più o meno quello che ho affermato - non esiste un supporto linguistico per questo, ma jQuery ha quindi apparentemente quello che ti serve per emularlo. – fredrik

+0

Sarei d'accordo con fredrik; non si può davvero emulare lo stesso comportamento in JS. In C#, puoi impostare una variabile sul valore atteso della chiamata, ad es. 'var name = attende getNameAsync();', ma non importa come lo si affetta, è necessario ricorrere all'uso di callback in JS. Non è un grosso problema, ma questo può portare a chiamate profondamente annidate se si hanno più funzioni asincrone che dipendono dal risultato asincrono di un'altra chiamata. In JS, lo stesso codice sarebbe 'var name; getName.then (newName => name = newName); ' –

7

JavaScript non ha (attualmente) una lingua equivalente a async/await. Ci sono various promise libraries disponibili per JavaScript che ti danno un equivalente approssimativo del tipo Task. Questo è un buon passo sopra i callback non elaborati, ma si finisce comunque con nidificazione imbarazzante o spaghetti callback in tutti gli scenari tranne quelli più semplici.

JavaScript ECMAScript 6 ("Harmony") include generators. L'ES6 è sulla buona strada per diventare ufficiale entro la fine dell'anno, ma probabilmente ci vorrà ancora un po 'di tempo prima di poter presumere che i browser dei tuoi utenti supportino i generatori.

Entro combining generators with promises, è possibile ottenere un valore equivalente a async/await.

1

Si potrebbe prendere in considerazione asyncawait che consente in modo efficace si scrive codice come segue

var foo = async (function() { 
    var resultA = await (firstAsyncCall()); 
    var resultB = await (secondAsyncCallUsing(resultA)); 
    var resultC = await (thirdAsyncCallUsing(resultB)); 
    return doSomethingWith(resultC); 
}); 

Al posto delle seguenti

function foo2(callback) { 
    firstAsyncCall(function (err, resultA) { 
     if (err) { callback(err); return; } 
     secondAsyncCallUsing(resultA, function (err, resultB) { 
      if (err) { callback(err); return; } 
      thirdAsyncCallUsing(resultB, function (err, resultC) { 
       if (err) { 
        callback(err); 
       } else { 
        callback(null, doSomethingWith(resultC)); 
       } 
      }); 

     }); 
    }); 
} 
0

Anche se questo non risponde alla "che cosa è l'equivalente di C# 's attendono in JavaScript?" domanda, il codice nella domanda può essere fatto funzionare piuttosto facilmente. La funzione bootbox.dialog restituisce un oggetto, in modo da poter regolare il codice mostrato in questo modo:

var dialog = bootbox.dialog({ 
    title: "Group", 
    buttons: { 
     success: { 
      label: "OK", 
      className: "btn-success", 
      callback: function() { 
       postForm(); 
       return false; // add this return here 
      } 
     } 
    } 
}); 

E poi la chiamata AJAX GETS regolato a:

function postForm() {   
    $.ajax({ 
     type: "POST", 
     url: $("#add-group").val(), 
     data: $("#form").serialize(), 
     success: function (data) { 
      // add this call to the underlying Bootstrap modal object 
      dialog.modal('hide'); 
     }, 
     error: function (XMLHttpRequest, textStatus, errorThrown) { 
      // Maybe inject an error message into the dialog? 
     } 
    }); 
} 
0

Con l'avvento della ES2017, la risposta a questa la domanda è asincrona/aspetta.
È la soluzione JS per "callback hell". È possibile attendere una promessa (equivalente all'attività) in una funzione asincrona.
Diversamente da C#, non è possibile chiamare una funzione asincrona in una funzione sincrona.

Vedere ECMA-draft 262 o MDN per maggiori informazioni.

Esempio:

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> 
<head> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> 

    <meta http-equiv="cache-control" content="max-age=0" /> 
    <meta http-equiv="cache-control" content="no-cache" /> 
    <meta http-equiv="expires" content="0" /> 
    <meta http-equiv="expires" content="Tue, 01 Jan 1980 1:00:00 GMT" /> 
    <meta http-equiv="pragma" content="no-cache" /> 

    <meta charset="utf-8" /> 
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 

    <meta http-equiv="Content-Language" content="en" /> 
    <meta name="viewport" content="width=device-width,initial-scale=1" /> 

    <meta name="google" value="notranslate" /> 


    <!-- 
    <meta name="author" content="name" /> 
    <meta name="description" content="description here" /> 
    <meta name="keywords" content="keywords,here" /> 

    <link rel="shortcut icon" href="favicon.ico" type="image/vnd.microsoft.icon" /> 
    <link rel="stylesheet" href="stylesheet.css" type="text/css" /> 
    --> 

    <title>Title</title> 

    <style type="text/css" media="all"> 
     body 
     { 
      background-color: #0c70b4; 
      color: #546775; 
      font: normal 400 18px "PT Sans", sans-serif; 
      -webkit-font-smoothing: antialiased; 
     } 
    </style> 


    <script type="text/javascript"> 
     <!-- 
     // http://localhost:57566/foobar/ajax/json.ashx 







     var ajax = {}; 
     ajax.x = function() { 
      if (typeof XMLHttpRequest !== 'undefined') { 
       return new XMLHttpRequest(); 
      } 
      var versions = [ 
       "MSXML2.XmlHttp.6.0", 
       "MSXML2.XmlHttp.5.0", 
       "MSXML2.XmlHttp.4.0", 
       "MSXML2.XmlHttp.3.0", 
       "MSXML2.XmlHttp.2.0", 
       "Microsoft.XmlHttp" 
      ]; 

      var xhr; 
      for (var i = 0; i < versions.length; i++) { 
       try { 
        xhr = new ActiveXObject(versions[i]); 
        break; 
       } catch (e) { 
       } 
      } 
      return xhr; 
     }; 

     ajax.send = function (url, callback, method, data, async) { 
      if (async === undefined) 
      { 
       async = true; 
      } 

      var x = ajax.x(); 
      x.open(method, url, async); 
      x.onreadystatechange = function() { 
       if (x.readyState == 4) { 
        callback(x.responseText) 
       } 
      }; 
      if (method == 'POST') { 
       x.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); 
      } 
      x.send(data) 
     }; 

     ajax.get = function (url, data, callback, async) { 
      var query = []; 
      for (var key in data) { 
       query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key])); 
      } 
      ajax.send(url + (query.length ? '?' + query.join('&') : ''), callback, 'GET', null, async) 
     }; 

     ajax.post = function (url, data, callback, async) { 
      var query = []; 
      for (var key in data) { 
       query.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key])); 
      } 
      ajax.send(url, callback, 'POST', query.join('&'), async) 
     }; 


     /////////// 



     function testAjaxCall() { 
      ajax.get("./ajax/json.ashx", null, function (bError, strMessage, iStatus) 
       { 
        console.log("args:", arguments); 

        console.log("Error:", bError); 
        console.log("Message:", strMessage); 
        console.log("Status:", iStatus); 
       } 
       , true 
      ); 

     } 
     --> 
    </script> 

</head> 
<body> 

    <script type="text/javascript"> 

     function ajaxGet(url, data) 
     { 
      var result; 

      return new Promise(function (resolve, reject) 
       { 

        ajax.get(url, data, function (bError, strMessage, iStatus) 
         { 

          // console.log("args:", arguments); 

          // console.log("Error:", bError); 
          // console.log("Message:", strMessage); 
          // console.log("Status:", iStatus); 

          result = bError; 
          resolve(result); 
         } 
         ,true 
        ); 

       } 
      ); 

     } 


     async function main() 
     { 
      var ajaxResult = await ajaxGet("./ajax/json.ashx"); 
      console.log("ajaxResult: ", ajaxResult); 
     } 

     async function lol() 
     { 
      var res = null; 

      var myPromise = new Promise(function (resolve, reject) 
      { 
       // Standard AJAX request setup and load. 
       var request = new XMLHttpRequest(); 

       // Request a user's comment from our fake blog. 
       request.open('GET', 'https://localhost:57566/ajax/json.ashx'); 

       /* 
       // Set function to call when resource is loaded. 
       // Onload same as onreadystatechange - onload added with XHR2 
       request.onload = function() 
       { 
        // internal server error/404 
        if (request.status === 200) 
        { 
         res = request.response; 
         // console.log(request.response); 
         console.log("onload- resolving promise"); 
         resolve(request.response); 
        } else 
        { 
         console.log("onload- rejectinv promise"); 
         reject('Page loaded, but status not OK.'); 
        } 
       }; 
       */ 


       request.onreadystatechange = function() 
       { 
        console.log("readystate:", request.readyState); 
        console.log("status:", request.status) 

        if (request.readyState != 4) return; 

        // XMLHttpRequest.DONE = 200, 0=cancelled 304 = redirect 
        //if (!(request.status != 200 && request.status != 304 && request.status != 0)) 
        if (request.status === 200) 
        { 
         console.log("successy") 
         resolve(request.responseText); // Success 
         return; 
        } 

        if (request.status != 200 && request.status != 0 && request.status != 304) 
        { 
         console.log('HTTP error ' + request.status); 
         // reject('Page loaded, but status not OK.'); 
         reject(new Error("Server error - Status NOK", "filename", "linenum666")); // Error 
         return; 
        } 

        if (request.status === 0) 
        { 
         console.log("cancelled:", request) 
         //resolve(null); // Cancelled, HTTPS protocol error 
         return; 
        } 

        reject(new Error("Strange error", "filename", "linenum666")); // Some Error 
       }; 

       // Set function to call when loading fails. 
       request.onerror = function() 
       { 
        // Cannot connect 
        console.log("OMG OnError"); 
        // reject('Aww, didn\'t work at all. Network connectivity issue.'); 
        reject(new Error("Aww, didn\'t work at all. Network connectivity issue.", "filename", "linenum666")); // Some Error 

       }; 


       if (!navigator.onLine) 
       { 
        console.log("No internet connection"); 
        reject("No internet connection"); 
       } 
       else 
       { 
        try 
        { 
         request.send(); 
        } 
        catch (ex) 
        { 
         console.log("send", ex.message, ex); 
        } 
       } 

      }); 

      return myPromise; 
     } 



     async function autorun() 
     { 
      console.clear(); 
      // await main(); 

      try 
      { 
       var resp = await lol(); 
       console.log("resp:", resp); 
      } 
      catch (ex) 
      { 
       console.log("foo", ex.message, ex); 
      } 



      console.log("I am here !"); 
     } 

     if (document.addEventListener) document.addEventListener("DOMContentLoaded", autorun, false); 
     else if (document.attachEvent) document.attachEvent("onreadystatechange", autorun); 
     else window.onload = autorun; 
    </script> 

</body> 
</html> 
Problemi correlati