admin管理员组文章数量:1201410
I want to turn an asynchronous function to the synchronous.
function fetch() {
var result = 'snap!';
$.getJSON(".gne?tags=cat&tagmode=any&format=json&jsoncallback=?", function messyCallback(data){
result = data;
});
return result;
}
document.write(fetch());
See in action
The result always will be 'snap!', because $.getJSON
run after fetch()
is done.
My first idea was:
function fetch() {
var result = 'snap!';
$.getJSON(".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.
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());
See in action
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.
Share Improve this question edited Feb 8, 2010 at 16:38 NVI asked Feb 8, 2010 at 15:59 NVINVI 15k16 gold badges68 silver badges104 bronze badges 4- Possible (likely?) duplicate - see stackoverflow.com/questions/1455870/…. – Jeff Sternal Commented Feb 8, 2010 at 16:11
- Jeff, I don't think so. I use JSONP call, which always synchronous. – NVI Commented Feb 8, 2010 at 16:21
- 1 @NV: JSONP is only synchronous when parsed as part of the HTML document. If it is added to the page using the DOM, it's async. – Andy E Commented Feb 8, 2010 at 16:45
- Whoops, I meant "which always asynchronous". – NVI Commented Feb 8, 2010 at 16:47
7 Answers
Reset to default 9See 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.
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.
Instead of writing helper methods like your fetch
that return a value, make them accept another function, a "receiver", to pass their result to:
function fetch(receiver) {
$.getJSON("blah...", function(data) {
receiver(data);
});
}
Obviously this is redundant because it's exactly how getJSON
already works, but in a more realistic example the fetch
function would process or filter the result somehow before passing it on.
Then instead of:
document.write(fetch());
You'd do:
fetch(function(result) { document.write(result); });
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.
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:
<script src="http://code.onilabs.com/latest/oni-apollo.js"></script>
<script type="text/sjs"> your StratifiedJS code here </script>
And your code would look like:
function fetch() {
return require("http").jsonp(
"http://api.flickr.com/services/feeds/photos_public.gne?" +
"tags=cat&tagmode=any&format=json", {cbfield:"jsoncallback"});
}
document.write(fetch());
Or if you really want to use jQuery in StratifiedJS:
require("jquery-binding").install();
function fetch() {
var url = "http://api.flickr.com/?format=json&...&jsoncallback=?"
return $.$getJSON(url);
}
document.write(fetch());
The docs are on http://onilabs.com/docs
The TameJS library is designed to deal with this problem.
You might write something like (untested):
var result = 'snap!';
await {
$.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?tags=cat&tagmode=any&format=json&jsoncallback=?", defer(result));
}
return result;
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".
I know this a little late but you can avoid callbacks with promises and await in async function
deliverResult = (options) => (
new Promise( (resolve, reject) => {
$.ajax(options).done(resolve).fail(reject);
})
)
getResult = async () => {
let options = {
type: 'get',
url: 'http://yourUrl.com',
data: {param1: 'arg1'}
}
console.log('waiting ..... ');
let result = await deliverResult(options);
console.log('**..waiting ended..**');
console.log(result);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type='button' onclick='getResult()' value='click me'/>
本文标签: Asynchronous programming in JavaScript without messy callbacksStack Overflow
版权声明:本文标题:Asynchronous programming in JavaScript without messy callbacks - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1738593173a2101634.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论