JavaScript 中的异步编程,无需混乱的回调
我想将异步函数转换为同步函数。
function fetch() {
var result = 'snap!';
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", function messyCallback(data){
result = data;
});
return result;
}
document.write(fetch());
结果始终是“snap!”,因为 $.getJSON
运行fetch()
完成后。
我的第一个想法是:
function fetch() {
var result = 'snap!';
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", function messyCallback(data){
result = data;
});
while (true) {
if (result != 'snap!') return result;
}
}
它不起作用并且还会关闭浏览器。
我读到了 JS 1.7 中的生成器和迭代器,但我不知道如何将其应用到我的问题上。
这个问题实际上与 jQuery 无关。 $.getJSON 可以是任何其他异步函数。
I want to turn an asynchronous function to the synchronous.
function fetch() {
var result = 'snap!';
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", function messyCallback(data){
result = data;
});
return result;
}
document.write(fetch());
The result always will be 'snap!', because $.getJSON
run after fetch()
is done.
My first idea was:
function fetch() {
var result = 'snap!';
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", function messyCallback(data){
result = data;
});
while (true) {
if (result != 'snap!') return result;
}
}
It doesn't work and also blow off the browser.
I read about generators and iterators in JS 1.7, but I have no idea how to apply it to my problem.
This question is not really about jQuery. Instead of $.getJSON could be any another asynchronous function.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
另请参阅此问题:停止 JavaScript 执行而不锁定浏览器
完全按照自己的意愿去做是行不通的。在单线程事件驱动环境中,您无法从异步创建同步(只能反过来!)。您应该拥抱该语言的异步特性,并围绕处理回调开发自己的一致风格,以便您的代码可读/可维护。例如,您可以选择不在回调闭包内执行任何实际工作,而只是为了清楚起见而调用另一个顶级函数/方法。
See this question also: Halt JavaScript execution without locking up the browser
Doing exactly what you want doesn't work. You can't create synchronousness from asynchronousness (only the other way around!) in a single-threaded event-driven environment. You should embrace the async nature of the language, and develop your own consistent style around handling callbacks so that your code is readable/maintainable. You could, for instance, choose to never do any real work inside a callback closure, but simply call another top-level function/method for clarity.
您想要推出自己的使用 $.ajax({async:false}) 的 $.getSyncJSON。请参阅:http://api.jquery.com/jQuery.ajax/。
不过,我必须建议您不要采取这种做法。您可以轻松锁定浏览器以阻止所有输入,使您的 UI 受网络支配。但如果您知道自己在做什么并且确定自己的用例,那就去做吧。
You want to roll your own $.getSyncJSON that uses $.ajax({async:false}). See: http://api.jquery.com/jQuery.ajax/.
I must advise you against this course of action, however. You can easily lock up the browser from all input, putting your UI at the mercy of the network. But if you know what you are doing and are sure of your use case, go for it.
不要编写像
fetch
这样返回值的辅助方法,而是让它们接受另一个函数(“接收器”),将结果传递给:显然这是多余的,因为它正是
getJSON< 的方式。 /code> 已经可以工作,但在更实际的示例中,
fetch
函数会在传递结果之前以某种方式处理或过滤结果。然后,而不是:
你会这样做:
生成器可用于使异步代码在风格上更加线性。每次您需要一些异步结果时,您都会生成一个函数来启动它,并且生成器将在结果可用时恢复。会有一些管理代码来保持生成器的运行。但这并没有多大帮助,因为生成器并不是跨浏览器的标准。
如果您有兴趣,这里有一篇关于使用生成器整理异步的 博客文章代码。
Instead of writing helper methods like your
fetch
that return a value, make them accept another function, a "receiver", to pass their result to:Obviously this is redundant because it's exactly how
getJSON
already works, but in a more realistic example thefetch
function would process or filter the result somehow before passing it on.Then instead of:
You'd do:
Generators can be used to make asynchronous code a lot more linear in style. Each time you needed some asynchronous result, you'd yield a function to launch it, and the generator would resume when the result was available. There'd be a bit of management code keeping the generator going. But this isn't much help because generators are not standard across browsers.
If you're interested, here's a blog post about using generators to tidy up asynchronous code.
JavaScript 语言有一个扩展,称为 StratifiedJS。它在每个浏览器中运行,并且允许您做到这一点:以同步/线性方式处理异步问题,而无需冻结浏览器。
您可以通过在网页中包含 Oni Apollo 来启用 Stratified JavaScript,例如:
您的代码如下所示:
或者,如果您确实想在 StratifiedJS 中使用 jQuery:
文档位于 http://onilabs.com/docs
There is an extension to the JavaScript language called StratifiedJS. It runs in every browser, and it allows you to do just that: handling asynchronous problems in a synchronous/linear way without freezing your browser.
You can enable Stratified JavaScript e.g. by including Oni Apollo in your webpage like:
And your code would look like:
Or if you really want to use jQuery in StratifiedJS:
The docs are on http://onilabs.com/docs
TameJS 库就是为了解决这个问题而设计的。
你可能会写一些类似的东西(未经测试):
The TameJS library is designed to deal with this problem.
You might write something like (untested):
jQuery 的下层 $.ajax() 函数 有更多选项,包括
async: [true|false]
(默认为 true)。尽管如此,在大多数情况下,您应该遵循 Ben 的建议并“接受语言的异步特性”。
The lower-level $.ajax() function from jQuery has more options, including
async: [true|false]
(default is true).Nevertheless, in most cases you should follow Ben's advice and "embrace the async nature of the language".
我知道这一点有点晚了,但你可以在异步函数中使用 Promise 和等待来避免回调
I know this a little late but you can avoid callbacks with promises and await in async function