在异步编程中,我们使用了很多回调,如下所示:
var running = function(){
do_sth();
$.post("/xxx", function(data){
do_sth2();
$.get("/ttt", function(data){
do_sth3();
}
}
}
我觉得事情应该是这样的:
var running = do_async(function(){
do_sth();
var data = $.post("/xxx");
do_sth2();
data = $.get("/ttt");
do_sth3();
});
我该怎么做?
并且有一个项目:https://github.com/JeffreyZhao/jscex
我觉得这个项目不是那么容易使用(实现是通过解析源代码)
也许在将来,我们对此有一个原生的javascript支持?
我对此做了一些研究,发现了一些讨论和库,供参考:
https://github.com/JeffreyZhao/jscex
推迟coffeescript https://github.com/jashkenas/coffee-script/issues/350合并到coffeescript: https://github.com/jashkenas/coffee-script/issues/350
tamejs图书馆 http://tamejs.org/
stratifiedjs http://onilabs.com/stratifiedjs
kaffeine http://weepy.github.com/kaffeine/
关于此的维基页面: http://en.wikipedia.org/wiki/Continuation-passing_style
添加库来支持它不是一件容易的事,
也许将来,javascript会添加一个“defer”关键字。
同样的问题:Pattern for wrapping an Asynchronous JavaScript function to make it synchronous
答案 0 :(得分:1)
回调是Javascript的重要组成部分。 Javascript旨在利用它们。我认为我们不会得到某种“同步器”。相反,我们正在获得越来越多的异步工具,比如Worker
s。
如果您对所有这些回调感到困惑,您最好尽快习惯它们。你会没事的,相信我。
无论如何,AJAX请求可以同步完成,但请记住,这会停止执行脚本。
答案 1 :(得分:1)
您可以查看Promises。有一些可用的实现,请参阅commonjs.org。所有这些都允许链接,因此您可以按如下方式编写代码:
function running(){
return do_sth()
.then($.post.bind($, "/xxx"))
.then(do_sth2)
.then($.get.bind($, "/ttt"))
.then(do_sth3);
// returns a Promise to run all these tasks
// ...or: a Promise for the result of the last of the chained tasks
}
如果你使用jQuery,这已经内置了deferred functionality(不是我最喜欢的Promise实现):
function running(){
do_sth();
return $.post("/xxx")
.then(do_sth2)
.then(function(){
$.get("/ttt")
.then(do_sth3);
});
}
答案 2 :(得分:1)
我确信你明白这种异步回调行为是设计上的,而不是一些不幸的疏忽。这是Node.js社区中出现的很多东西(Node使用类似的事件循环),并且已经基于光纤,线程等开发了许多替代方案。最近的一些讨论是{{3} }和here,其中也涵盖了许多替代方案。
节点论坛上的异步库上的编辑 here,包括讨论
一些贡献者写了那些/写过其他流控制库,我肯定发现它值得一试。
我最近读过的其他内容
我不确定这是一条我要走的路,除非你特别需要这种行为(例如@MaxArt提到的浏览器中的工作人员,或者你的代码特别适合多线程(等)模型)因为大多数这些解决方案实际上是下面的单螺纹环。您可以通过传递/调用命名函数来避免过多讨厌的嵌套,例如
function a() {
somethingAsync(function (val) { b(val); });
}
function b(val) { ... }
答案 3 :(得分:0)
由于JavaScript完全是单线程的,因此绝对无法同步异步代码。
我建议你练习掌握一切。也许你可以尝试setTimeout
功能。给它一个回调,并可能在控制台上显示"Hello, World!"
。并且,将数字0作为最后一个参数传递。
然而,据说,你可以借助库来“美化”异步代码。
有一个特别是我最喜欢的。它叫做async.js。我一直使用它来保持深度嵌套的异步调用看起来更加同步(即MongoDB查询)。
async.waterfall([
// Call to the first asynchronous call...
function (callback) {
setTimeout(function () {
callback(null, "Hello, World!");
}, 0);
},
// That needs to make another...
function (callback, message) {
console.log(message);
setTimeout(function () {
callback(null, "It's a nice day!");
}, 0);
},
// Another...
function (callback, message) {
console.log(message);
setTimeout(function () {
callback(null, "Bye, now!");
}, 0);
},
// And another.
function (callback, message) {
console.log(message);
}
]);
// Without making the entire thing hopelessly nested deeply.