有沒有辦法執行不凍結瀏覽器的同步AJAX查詢?在我看來,在大多數情況下,同步請求更容易處理,但是阻止其他代碼執行的事實是一個真正的殺手。有沒有辦法讓同步AJAX沒有負面影響? (是的,我意識到術語「同步AJAX」是一個矛盾)。非阻塞同步AJAX
回答
我會舉一個允許這種行爲的壞結果的例子。
比方說你有這樣的程序:
<script>
var file = "foo.json";
function nullIt() {
file = null;
}
function loadFile() {
if (file != null) {
synchronousLoad(file);//imagine the load takes 5 seconds
alert("i just loaded: " + file);
}
}
window.onload = loadFile;
</script>
<button onclick="nullIt()">click me</button>
壞事這裏 -
- 而
synchronousLoad()
阻止5秒,用戶點擊該按鈕,事件處理程序跑得快完成。 - 現在
file
變量爲空。 synchronousLoad()
飾面和回報,對代碼- 但
file
下一行讓執行履歷是現在爲空,並且該消息輸出給用戶是斷開的。
真正的問題在這裏你不能以同樣的方式推理你的代碼了。僅僅因爲第5行的一些事實是 是真的,並不意味着它在下一行仍然是真的。這使得編寫一個無錯誤的程序非常困難。
一些編程語言支持多線程,並且您必須處理這些問題,儘管您有工具來幫助處理這些問題。但是,對於程序員來說,這還是很多額外的工作。
比較而言,使用回調來執行異步操作是ez-mode。
啊,優點。就我個人而言,我寧願把這些「競爭條件」(如果你可以稱之爲)的機會,但很高興看到爲什麼事情是這樣的理由。 – Ajedi32
否。根據定義,同步是阻塞的。在流程完成之前,任何事情都可以繼續。這包括Web瀏覽器中的其他用戶界面。
它的假設是異步的,所以最好的方法是設計代碼異步工作。
我不認爲這是可能的。您可以使用異步方法並使用AJAX完成事件,而不是嘗試使用同步查詢。使用jQuery.ajax()
例
jQuery.ajax({
url: "URL HERE",
data: "whatever you are sending"
}).done(function (data) {
// Do things with data
});
因此,代替使用一個同步請求,則可以使用異步請求和之後的請求已經完成剛剛執行代碼。所以,它不會凍結你的瀏覽器。
是的,但這正是我試圖通過做一個同步請求避免。我的代碼的當前執行路徑中沒有任何內容需要執行,直到請求完成後才執行同步請求。 我只是不希望它在等待時阻止我的代碼的其他部分。 – Ajedi32
@ Ajedi32它根本不乾淨 - 特別是因爲它*不能用單個執行上下文(例如瀏覽器JavaScript使用的上下文)工作。另外,當使用多個執行上下文時(即線程或者延續),還有其他的考慮和問題需要處理:隱式的原子執行被刪除,並且[更多形式的]競爭條件必須被防範。 – user2246674
@ Ajedi32使用promise(特別是在jQuery 1.8+中實現並由[Promises/A](http://wiki.commonjs.org/wiki/Promises/A)編寫的'then')可以極大地清理異步代碼用法。我發現Promise模型比以前的成功/錯誤回調要更加一致和乾淨。 – user2246674
由於其他答案中列出的原因,在沒有阻止瀏覽器中的其他事件的情況下,沒有辦法執行同步AJAX調用。但是,如果代碼複雜性是您希望避免異步方法調用的主要原因,那麼您可能對Javascript交叉編譯器streamline.js感興趣,它允許您編寫異步方法調用,就好像它們是同步的,並獲取結果與您異步編寫該調用的結果相同。
從項目的GitHub的頁面:
streamline.js是一種語言工具,以簡化異步JavaScript編程 。
而不是寫像毛毛代碼:
function archiveOrders(date, cb) { db.connect(function(err, conn) { if (err) return cb(err); conn.query("select * from orders where date < ?", [date], function(err, orders) { if (err) return cb(err); helper.each(orders, function(order, next) { conn.execute("insert into archivedOrders ...", [order.id, ...], function(err) { if (err) return cb(err); conn.execute("delete from orders where id=?", [order.id], function(err) { if (err) return cb(err); next(); }); }); }, function() { console.log("orders have been archived"); cb(); }); }); }); }
你寫:
function archiveOrders(date, _) { var conn = db.connect(_); conn.query("select * from orders where date < ?", [date], _).forEach_(_, function(_, order) { conn.execute("insert into archivedOrders ...", [order.id, ...], _); conn.execute("delete from orders where id=?", [order.id], _); }); console.log("orders have been archived"); }
和精簡轉換代碼,需要回調的關懷!
沒有控制流API來學習!你只需要遵循一個簡單的規則:
用下劃線替換所有的回調函數,並寫下你的代碼,好像所有的 函數都是同步的。
有關streamline.js更多信息,閱讀博客文章Asynchronous Javascript – the tale of Harry。
在即將發佈的ECMAScript 2016(ES7)標準中,有一組新的語言關鍵字設計用於執行與您看起來非常相似的操作,稱爲async
和await
。
這些關鍵字不允許「非阻塞同步AJAX」,但他們讓你寫異步代碼的方式,看起來同步。這裏有一個簡單的例子:
// Let's say you have an asynchronous function that you want to call in a synchronous
// style...
function delayedEval(delay, func) {
// First, ensure that the function returns a Promise object. If it doesn't, wrap it with
// another function that does.
return new Promise((resolve, reject) => {
setTimeout(() => resolve(func()), delay)
})
// For more on Promises, see https://goo.gl/uaoDuy (MDN link)
}
// Then, declare a function as asynchronous. This causes it to return a Promise that
// resolves to its return value, instead of returning its return value directly.
async function delayedHello() {
// Inside an async function, you can call other async functions like this, which looks
// very much like a synchronous call (even though it isn't).
let message = await delayedEval(1500,() => "Hello, world!")
console.log(message)
}
// This returns (a Promise) immediately, but doesn't print "Hello, world!" until 1.5
// seconds later. (At which point it resolves the Promise.)
delayedHello()
基本上,而不是「無不良副作用同步AJAX」,async
和await
讓你異步 AJAX沒有所有其負面影響。 (具有許多用於處理回調的邏輯的亂碼)。
async
和await
是ES7標準中"async functions" candidate recommendation的一部分。
- 1. jQuery同步非阻塞AJAX調用
- 2. 同步阻塞?
- 3. Opengl的不同步/非阻塞地圖
- 4. 默認爲Javascript同步(阻止)或異步(非阻塞)
- 5. 異步與非阻塞
- 6. 阻塞與同步,非阻塞和異步之間有什麼區別?
- 7. 同步方法執行時,非同步方法是否阻塞
- 8. mpi:阻塞與非阻塞
- 9. 類似AJAX的非阻塞異步Python請求
- 10. C++非阻塞異步計時器
- 11. 異步/非阻塞查詢中的SQLDeveloper
- 12. 非阻塞django?
- 13. 非阻塞setTimeout
- 14. 非阻塞spmd
- 15. 非阻塞pthread_join
- 16. PyGTK非阻塞
- 17. Javascript非阻塞
- 18. 非阻塞stdio
- 19. 帶延遲的阻塞/非阻塞
- 20. 嵌套Socket阻塞非阻塞SocketHi
- 21. 非阻塞PASV襪子和阻塞
- 22. 是renderer.render()阻塞還是非阻塞?
- 23. 非阻塞寫入和阻塞recv
- 24. 「非阻塞與背景同步?」的縮寫名稱
- 25. 瞭解非阻塞線程同步和Thread.MemoryBarrier
- 26. 將同步方法轉換爲非阻塞算法
- 27. 非阻塞連接
- 28. 非阻塞的PipedStreams?
- 29. WPF:非阻塞UI
- 30. C#非阻塞Socket.Connect()
我不這麼認爲......我建議你學習承諾,使AJAX工作更容易。 – elclanrs
@hexacyanide對不起,我猜這是措辭不佳。我的意思是它不凍結瀏覽器或阻止我的代碼中的其他事件觸發。 – Ajedi32
即使「非阻塞同步」不是矛盾,在單執行(又名單線程)環境中這樣的構造是不可能的。瀏覽器JavaScript中的替代方案和解決方案實際上是「非阻塞*異步*」。 – user2246674