2014-04-24 17 views
8

我使用jQuery庫稱爲bootbox在JavaScript/jquery中,C#的等價值是多少?

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; 
     } 
    }); 
} 

當我點擊「OK」按鈕,除非我返回一個錯誤的值是這樣的:

callback: function() { 
    return false; 
} 

對話框將關閉。

在回調函數中,我打電話postForm這是一個函數,使AJAX調用我的服務器端執行某些操作。根據該操作的結果,我想保持對話框仍然打開。

但是因爲這是一個AJAX調用,並且結果需要一段時間纔會回來,所以無論我的結果如何,該對話框都會在postForm()之後立即關閉。

如何告訴javascript等待ajax調用的結果?

這將是巨大的,如果我可以做這樣的事情:

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

JavaScript是不是多線程,因此等待是不可能的。只有同步操作(代碼按順序均勻執行)和異步操作(操作在完成後調用回調函數)。解決方法是jquery promise(),這實際上是間接回調。 – setec

+0

所以我可以在promise()中包裝postForm()? –

+0

我想你可以在'postForm()'中嘗試'$ .when'。我不確定,但它應該工作 –

回答

6

我認爲Promises正是你所問的。

.promise()

返回無極對象,觀察當某種類型綁定到集合中的所有動作,排隊與否,已經完成。例如

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

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

有關的詳細信息請參閱:https://api.jquery.com/promise/

遞延無極更接近異步行爲

deferred.promise()

的deferred.promise()方法允許異步函數來防止其他代碼干擾其內部請求的進度或狀態。無極公開只有附加其他處理或確定狀態(thendonefailalwayspipeprogressstate)所需的遞延方式,而不是那些改變狀態(resolverejectnotifyresolveWithrejectWith ,和notifyWith)。

如果提供了目標,deferred.promise()會將方法附加到它上面,然後返回這個對象而不是創建一個新對象。這對將Promise行爲附加到已存在的對象很有用。

如果您正在創建延遲,請保留對延遲的引用,以便在某個時刻解決或拒絕它。通過deferred.promise()僅返回Promise對象,以便其他代碼可以註冊回調或檢查當前狀態。

實施例:

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); 
    } 
); 

有關詳細信息,請參閱Deferred對象的文檔:http://api.jquery.com/category/deferred-object/

jQuery.when()

提供一種方法來執行基於一個或多個對象的回調函數,通常表示異步事件的延遲對象。例如:

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

可以擴展您的答案以反映它對於我的場景的外觀嗎? –

+0

我不確定'bootbox',似乎點擊確定有默認的動作來隱藏該庫中的對話框。在簡單的對話框中,我只通過隱藏對話框來完成同樣的事情。 –

+0

如果我在回調中返回false,它將不會返回關閉對話框 –

4

你不能。 JS中沒有相當於await

您必須通過調用postForm返回false來模擬它,然後在AJAX調用中執行回調函數時關閉對話框。

+2

我認爲我們可以模擬等同於在jQuery中使用'promise'的方法。 –

+0

是的,看起來你可以,並且它或多或少是我所說的 - 沒有語言支持,但jQuery顯然具有你需要模擬它的東西。 – fredrik

+0

我同意fredrik;你不能真正模仿JS中的相同行爲。在C#中,您可以爲呼叫的等待值設置一個變量,例如'var name = await getNameAsync();',但不管你如何分片,你必須求助於在JS中使用回調。沒有什麼大不了的,但是如果你有多個依賴於另一個調用的異步結果的異步函數,這可能導致深度嵌套調用。在JS中,相同的代碼將是'var name; getName.then(newName => name = newName);' –

7

JavaScript沒有(當前)具有相當於async/await的語言。有various promise libraries可用於JavaScript,給你一個粗略的相當於Task類型。這是原始回調之上的一個很好的步驟,但在最簡單的情況下,最終還是會出現尷尬的嵌套或回調意大利式麪條。

JavaScript ECMAScript 6(「Harmony」)預計包含generators。 ES6有望在今年晚些時候正式上線,但之後可能會有一段時間,然後才能安全地假設用戶的瀏覽器支持生成器。

通過combining generators with promises,您可以實現等效的真實async/await

1

你可以考慮asyncawait你寫的代碼,有效地允許如下

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

取而代之的是以下

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

雖然這並不回答「什麼的C#的在等待相當於JavaScript的?」問題,問題中的代碼可以很容易地工作。該bootbox.dialog函數返回一個對象,這樣你就可以調整像這樣顯示的代碼:

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

然後Ajax調用被調整爲:

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

隨着ES2017的到來,這個問題的答案問題是異步/等待。
這是JS回答「回撥地獄」的解決方案。 您可以在異步函數中等待Promise(等同於任務)。
與C#不同,無法在同步函數中調用異步函數。

請參閱ECMA-draft 262MDN瞭解更多信息。

實施例:

<!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> 
相關問題