I have this function in Flash:
public function checkFile(file:String):Boolean{
var b:Boolean;
var responder:Responder = new Responder(function(reply:Boolean):void{
b=reply;
msg("vid_"+file+".flv "+ "exists? " + reply);
setState("ready");
status = "ready";
},
function(res:Object):void{
trace("checkFile call failed");
});
mync.call("checkFile",responder,"vid_"+file);
return b;
}
I can confirm that the reply variable is true, but return b ends up false:
This is the javascript I use to call the flash function:
function checkFile(){
alert(thisMovie("vidRecorder").checkFile(currentVid));
}
And that opens up a message box saying false, while the flash file displays true
What's going on? How can I fix it so that my function returns the same value as reply?
This happens because the anonymous function in your responder is executed asynchronously.
When your checkFile() function returns the value of b is still false. Eventually, your anonymous function is executed and b gets set to true ... but it's too late in this case, as your checkFile() function has already returned false.
To work around this, you might consider doing this in a slightly different fashion:
When your anonymous function is executed, have it call out to javascript with the asynchronous response. Something like this:
public function checkFile(file:String):void {
var responder:Responder = new Responder(function(reply:Boolean):void{
msg("vid_"+file+".flv "+ "exists? " + reply);
setState("ready");
status = "ready";
ExternalInterface.call('someJavascriptFunction', reply);
},
function(res:Object):void{
trace("checkFile call failed");
});
mync.call("checkFile",responder,"vid_"+file);
// note we no longer return a value here
}
In the above code, we call a new Javascript function and provide it the result of the asynchronous operation.
Related
Can I call a timeout function on the returned element in this if statement?
var data = 'some stuff';
if(data){
return jQuery('<div class="thisDiv"></div>').html(data);
}
I've tried the following:
if(data){
setTimeout(function() {
return jQuery('<div class="thisDiv"></div>').html(data);
}, 100);
}
But I get this error in my console:
Uncaught TypeError: Cannot read property 'nodeType' of undefined
The return statement will return from the anonymous function you passed into the setTimeout function, not the function enclosing the scope of the if statement. Try passing a callback into the function containing the if statement, then calling that callback with the data as a parameter.
function delayedReturn(callback) {
if(data) {
setTimeout(function() {
callback(jQuery('<div class="thisDiv"></div>').html(data));
}, 100);
}
}
No. You cannot use setTimeout to delay when a function will return. It is not a sleep function. It puts a function on a queue to run later, it doesn't stop all processing for a period of time.
function a() {
return 1;
}
var x = a();
In the above you have a single function which has a return statement. The value it returns is assigned to x.
function b() {
setTimeout(function c() {
return 1;
}, 1000);
}
var y = b();
Now you have two functions. b has no return statement, so it returns undefined and undefined is stored in y.
b uses setTimeout to call c, and c has a return statement. setTimeout doesn't do anything with return values though, so the return value of c is discarded.
Any time you are dealing with asynchronous functions, you have to do something with the data inside the asynchronous callback (such as call another function and pass the data as an argument). There is no going back, it is too late for that.
You could return a Promise from b though. That would allow other code to use the value of y to bind event handlers that will fire when the timeout expires.
You certainly can, you'd need to remove the return and use a valid selector to target your div.
Something like this would work:
HTML
<div class="thisDiv">test</div>
Javascript:
var data = 'some stuff';
if(data){
setTimeout(function() {
jQuery('.thisDiv').html(data);
}, 100);
}
You can see it working here: https://jsfiddle.net/ckkz1wbf/
Question, Why are you using:
jQuery('<div class="thisDiv"></div>')
Are you try to create an element, if that the case, you could use delay from jquery.
function fn(){
var data = 'some stuff';
if(data){
return jQuery('<div class="thisDiv"></div>').delay(100).html(data);
}
}
I am writing a jQuery plugin that lets users add references to their article. Basically, when the enter key is pressed while the user is focused on the reference input, the script checks the URL through my AJAX script to make sure that it's a working URL. If it's valid, a button is added to a list of references that the user can see. It will also update a hidden input that contains a comma-separated list of URL's.
I am very new to the concept of JS exceptions... I am currently getting an error saying Uncaught [object Object]. The error happens where I throw the variable 'info'. Any ideas?
(function($){
$.fn.extend({
references : function(options) {
var defaults = {
sample_div : '#sample-ref',
remove_button : '#removereference',
update_div : '#references',
hidden_input : 'input[name="references"]',
saved_input : 'input[name="saved-refs"]',
ajax_url : 'ajax.php',
search_input : '#reference'
};
var options = $.extend(defaults, options);
var count = 0;
function addReferenceBlock(ref_title){
var replacements = {
ref_title : ref_title,
ref_url : ref_url
};
var block = $(options.sample_div).html();
$.each(replacements, function(index, value){
block.replace(new RegExp('{'+index+'}', 'g'), value);
});
$(options.update_div).append(block);
}
function checkReference(url){
var postData = 'reference='+url;
$.ajax(
{
dataType: "xml",
type: "POST",
data : postData,
cache: false,
url: options.ajax_url
})
.done(function(xml, textStatus, jqXHR){
if(textStatus === 'success'){
$(xml).find('success').each(function(){
console.log('checking '+url+'...');
var info = $(this).find('pagetitle');
throw info;
});
$(xml).find('error').each(function(){
throw false;
console.log($(this).find('message').text());
});
} else {
console.log(jqXHR);
}
});
}
function init(element, options){
$(options.search_input).enterKey(function(e){
try {
checkReference($(options.search_input).val());
} catch($status){
if($status !== false){
addReferenceBlock($status);
updateReferenceInput($(options.search_input).val());
} else {
alert($status);
}
}
e.preventDefault();
});
}
return $(this).each(function(){ init(this, options); });
}
});
})(jQuery);
Your try block calls the checkReference function. Your checkReference function calls done. done does not call the anonymous function which throws your error; it sets up an event handler so it can be called by the system later. Thus, your stack trace is not what you think it is.
EDIT
Why does "done" not call the code inside of it?
Because if it did, it would not be asynchronous. Let's mock this with setTimeout rather than AJAX, same principles apply:
function foo(how) {
throw("In foo " + how + " (look at the stack trace by clicking on the triangle)");
}
function callFooAsynchronously() {
console.log("calling foo asynchronously");
setTimeout(function() {
foo("asynchronously");
}, 1000);
console.log("finished calling foo asynchronously");
}
function callFooSynchronously() {
console.log("calling foo synchronously");
foo("synchronously");
console.log("finished calling foo synchronously");
}
function main() {
callFooAsynchronously();
callFooSynchronously();
}
main();
The output is as follows:
calling foo asynchronously js:18
finished calling foo asynchronously js:22
calling foo synchronously js:26
Uncaught In foo synchronously (look at the stack trace by clicking on the triangle) js:14
foo js:14
callFooSynchronously js:27
main js:34
(anonymous function) js:37
Uncaught In foo asynchronously (look at the stack trace by clicking on the triangle) js:14
foo js:14
(anonymous function)
The synchronous call will start, then throw an exception. Due to the exception, "finished calling foo synchronously" is never displayed. The stack trace shows call from the snippet execution environment, calling to main, which calls callFooSynchronously, which, ultimately, calls foo.
The asynchronous call will display the starting message, attach a timeout handler, then display the finished message, then exit. This concludes callFooAsynchronously. One second later, the browser will remember there is something it needs to do, and this is reflected in the stack trace: the anonymous function passed to setTimeout is run, which in turn runs foo. Note how main and callFooAsynchronously are not a part of the stack trace: they have set the alarm, then left the building. callFooAsynchronously, despite its name, never calls foo, and neither does setTimeout.
The browser calls the anonymous function in setTimeout directly, just as it calls directly the onreadystatechange function on an XMLHttpRequest (the function that ultimately calls the function you passed to done), which is attached, but not called, by jQuery.ajax.
If done called your function, it would be executed immediately after you made the ajax call, and not when the response arrives, because that is when done gets executed.
In JS, you can throw errors using error-strings like: throw new Error('You did something wrong')
So in your case, maybe you can try: throw new Error(info.text()) which will fetch the text inside the .pagetitle element.
Is this what you want?
Below shown is js code which makes call to the native functions in iOS and Android, this function is called from another js method.Since the js calls to this function is asynchronous.we could not return any values in iOS.but in Android we could return the values without any issue.In iOS control dosent wait until i get the response.Actually we are not suppose to modify this function call otherwise we can pass a callback method from the caller function.Please help me to solve this issue
VestaPhoneBridge.IsAvailable = function(featureName)
{
if(isAndroid()) {
if(typeof VestaJavascriptInterface !== 'undefined')
{
return VestaJavascriptInterface.isAvailable(featureName);
}
return false;
}
else {
bridge.callHandler('initiateIsAvailableFunction',featureName,function(response) {
return response;
})
}
};
I assume you're talking about this line.
bridge.callHandler('initiateIsAvailableFunction',featureName,function(response) {
return response;
})
The problem will most likely be your return. The anonymous function you are passing as a callback will be called whenever the async request is finished. This means that it will be called by something inside the callHandler code path.
Your function is then returning to that function, and not the VestaPhoneBridge.IsAvailable function. Your callback should set values, and perform changes instead of returning a value.
Example
function Foo(callback) {
callback(); // 42 is returned here, but not assigned to anything!
}
function Bar() {
var baz = Foo(function() {
// You want to return 42. But here you are in a totally different function
// scope! You are in the anonymous function's scope, not Bar, so you are not
// returning anything to the caller of Bar().
return 42;
}
alert(baz); // Foo doesn't return anything, so this is undefined!
}
alert(Bar()); // This is also undefined, nothing was returned.
Perhaps this has already been addressed, but couldn't find a suitable answer here. Apologies if it's the case. Here's the issue :
function Aclass(){
this.value1 = "a first value"
this.value2 = pulldata()
function pulldata(){
$.getJSON("data.json",function(data){
return data
})
}
}
var obj = new Aclass()
console.log(obj.value1)
console.log(obj.value2)
Result : "a first value" then "undefined"
The data var isn't available out of the pulldata's scope, and I'm not sure what's the best way around this.
Your pullData() function doesn't actually return anything explicitly, so its return is undefined - which means what you are seeing when you log obj.value2 is correct (though undesired).
Inside pullData() you are calling $.getJSON() and passing it an anonymous function as a callback, and it is that anonymous function that returns data but the return doesn't go anywhere because the ajax call is asynchronous and the callback doesn't occur until later.
You could try this:
function Aclass(classInitialisedCallback){
var self = this;
this.value1 = "a first value";
this.value2 = "not available yet";
$.getJSON("data.json",function(data){
self.value2 = data;
if (typeof classInitialisedCallback === "function")
classInitialisedCallback(self);
});
}
var obj = new Aclass(function(newInstance) {
// can use obj or newInstance to refer to the object
console.log(obj.value1);
console.log(newInstance.value2);
});
That is, set up your Aclass() constructor to take a parameter that is a callback function to be executed when the class is ready, i.e., after the result from $.getJSON() is available.
$.getJSON makes an asynchronous ajax call to your "data.json" URL. The second argument you've given it is the callback, which is called when the ajax call is finished.
Your pulldata function, however, just runs through without waiting for the answer and, thus, returns undefined.
It's not possible to do exactly what you're trying to do with asynchronous calls (and you should never use synchronous calls).
You'll have to rewrite your code to do your stuff in the callback instead. The callback is your "function(data){}" argument.
If the function you called wasn't asynchronous however, this is how the JS scope works and should've solved your problem:
function Aclass() {
var that = this;
this.value2 = 'not set';
var pullData = function() {
someCallToSomethingWithACallback(function() {
that.value2 = 'set';
}
}
}
This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 9 years ago.
I have the following jQuery Function. I'm trying to return the GUID value shown here in the alert(); The alert works fine and the value is populated, however I can't seem to assign it to a variable and return its value.
Ultimately I need to access the GUID value in other functions, etc. Everything I've tried only displays as undefined.
I'd like to do something like this:
function trackPage(){
var elqTracker = new jQuery.elq(459);
elqTracker.pageTrack({
success: function() {
elqTracker.getGUID(function(guid) {
alert(guid);
var returnValue = guid;
});
}
});
return returnValue;
}
var someGuid = trackPage();
So, this question has been asked a million times over, and I'm sure that everyone (myself included) tried this once.
It is just the nature of an asynchronous call, you can't use their results as a return value. Thats why they have you passing in a function that gets the result of the call, they can't return it either! Also notice that the elqTracker.pageTrack() function call returns IMMEDIATELY, therefore your returnValue is simply undefined.
Most people (see dfsq's answer) solve this problem by introducing a callback function as a paramater. This method is tried, and true – however jQuery has $.Deferred. This allows you to make your own asynchronous logic return a promise which you can then attach any number of callbacks to:
function trackPage(){
var elqTracker = new jQuery.elq( 459 ),
dfd = $.Deferred();
elqTracker.pageTrack({
success: function() {
elqTracker.getGUID(function( guid ) {
dfd.resolve( guid );
});
}
});
return dfd.promise();
}
// example use:
trackPage().done(function( guid ) {
alert( "Got GUID:" + guid );
});
Notice now that your trackPage() returns an object that you can attach callbacks to? You don't have to attach them immediately either.
var pageHit = trackPage().done(function( guid ) {
alert( "Page Hit GUID:" +guid );
});
$("button").click(function() {
pageHit.done( function( guid ) {
alert( "Clicked on Page GUID:" + guid );
});
});
Also, the jQuery AJAX module always returns promises as well, so the interface for all your AJAX stuff should be very similar if you make your own logic return promises.
As a side note: I'd like to point out that your var returnValue was in the wrong "scope" anyway. It needed to be declared in the outer scope of the trackPage function. Even with this fix, the concept still doesn't work.
Since you have asynchronous call the way you are trying to write code is not going to work (because by the moment of return returnValue; in the trackCode return value is not yet defined). Instead you should pass callback into trackPage:
function trackPage(callback) {
var elqTracker = new jQuery.elq(459);
elqTracker.pageTrack({
success: function() {
elqTracker.getGUID(function(guid) {
alert(guid);
// Instead of this: var returnValue = guid;
// You should use your callback function
callback(guid);
});
}
});
return returnValue;
}
trackCode(function(guid) {
// perform some actions with guid
});