Javascript 非阻塞同步AJAX
有没有一种方法可以执行不冻结浏览器的同步AJAX查询?在我看来,在大多数情况下,使用同步请求要容易得多,但它们阻止代码的其他部分执行的事实是一个真正的杀手。有没有一种方法可以在没有负面影响的情况下获得同步AJAX?(是的,我意识到术语“同步AJAX”是一个矛盾修饰法。)不。根据定义,同步就是阻塞。在流程完成之前,任何操作都无法继续。它包括web浏览器中UI的其余部分Javascript 非阻塞同步AJAX,javascript,ajax,Javascript,Ajax,有没有一种方法可以执行不冻结浏览器的同步AJAX查询?在我看来,在大多数情况下,使用同步请求要容易得多,但它们阻止代码的其他部分执行的事实是一个真正的杀手。有没有一种方法可以在没有负面影响的情况下获得同步AJAX?(是的,我意识到术语“同步AJAX”是一个矛盾修饰法。)不。根据定义,同步就是阻塞。在流程完成之前,任何操作都无法继续。它包括web浏览器中UI的其余部分 它应该是异步的,所以最好的方法是设计异步工作的代码。我认为这是不可能的。您可以使用异步方法并使用ajaxdone事件,而不是尝试使
它应该是异步的,所以最好的方法是设计异步工作的代码。我认为这是不可能的。您可以使用异步方法并使用ajaxdone事件,而不是尝试使用同步查询 使用jQuery.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>
var file=“foo.json”;
函数nullIt(){
file=null;
}
函数loadFile(){
如果(文件!=null){
synchronousLoad(文件);//假设加载需要5秒钟
警报(“我刚刚加载:+文件);
}
}
window.onload=loadFile;
点击我
这里的坏事是-
- 当
阻塞5秒钟时,用户单击按钮,事件处理程序将快速运行到完成李>synchronousLoad()
- 现在
变量为空李>文件
完成并返回,让执行在下一行代码上继续synchronousLoad()
- 但是
现在为空,向用户输出的消息被中断文件
相对而言,使用回调来执行异步操作是ez模式。出于其他答案中概述的原因,如果不阻止浏览器中的其他事件,则无法执行同步AJAX调用 但是,如果代码复杂性是您希望避免异步方法调用的主要原因,那么您可能会对Javascript交叉编译器感兴趣,它允许您像同步一样编写异步方法调用,并像异步编写调用一样获得相同的结果 从项目的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();
});
});
});
}
功能归档订单(日期,cb){
数据库连接(功能(错误,连接){
如果(错误)返回cb(错误);
conn.query(“从日期<?”的订单中选择*,[date],函数(err,订单){
如果(错误)返回cb(错误);
helper.each(订单,函数)(订单,下一个){
conn.execute(“插入archivedOrders…”,[order.id,…],函数(err){
如果(错误)返回cb(错误);
conn.execute(“从订单中删除,其中id=?”,[order.id],函数(err){
如果(错误)返回cb(错误);
next();
});
});
},函数(){
console.log(“订单已存档”);
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");
}
功能归档订单(日期){
var conn=db.connect(u);
conn.query(“从日期<?”的订单中选择*,[date],。).forEach(uu,函数(u,订单){
conn.execute(“插入到archivedOrders…”,[order.id,…],u);
conn.execute(“从订单中删除,其中id=?”,[order.id],389;);
});
console.log(“订单已存档”);
}
简化代码转换并处理回调
无需学习控制流API!你只需要遵循一个简单的规则:
用下划线替换所有回调,并将代码编写为
功能是同步的
有关streamline.js的更多信息,请阅读博客文章。在即将发布的ECMAScript 2016(ES7)标准中,有一组新的语言关键字,它们的设计与您所寻找的非常相似,称为
async
和wait
这些关键字不允许“非阻塞同步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
和wait
让您获得没有负面影响的异步AJAX。(混乱的代码,包含大量处理回调的逻辑。)
async
和await
是ES7标准中的一部分。我不这么认为。。。我建议您学习承诺,让使用AJAX更容易。@对不起,我想这是措词不当的。我的意思是,它不会冻结浏览器或阻止代码中的其他事件触发。即使“非阻塞同步”不是矛盾,在单执行(也称为单线程)环境中也不可能实现这种构造。另一种选择,实际上是浏览器JavaScript中的解决方案,是“非阻塞异步”。相关:在这里也可能有帮助:是的,但这正是我试图通过执行同步请求来避免的。在我的代码的当前执行路径中,没有任何东西需要在请求完成之前执行,因此只执行
// 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()