I could explain my problem but it is likely easier to demonstrate it...
If you take a look at http://jsfiddle.net/XxT2B/ you'll see my issue. I am having trouble figuring out how to pass an action to a function. You'll see what I mean.
Please note that the action could be different based on what calls the function. The action may be an alert on time and something different the next.
Here is my code...
function abc(action)
{
//Do a bunch of stuff first and then do the action sent to this function
alert('This function is named "abc"');
//This is the part I do not know how to do.
//The action might be an alert or something totally different so I can't just pass text
//I need to know how to execute the action passed.
action;
}
abc('alert("I like pizza")');
You can pass a function as a parameter to another function.
function abc(action)
{
//Do a bunch of stuff first and then do the action sent to this function
alert('This function is named "abc"');
action();
}
abc(function(){
alert("I like pizza");
});
You can pass a function into abc(), but be sure to sanitize
function abc(action)
{
alert('This function is named "abc"');
if(typeof(action) == "function") { //sanitize
action();
}
}
abc('alert("I like pizza")'); //will execute without a problem
abc(50); //will not run, since 50 is not a function
The good way:
Pass it as a function:
function abc(action)
{
//Do a bunch of stuff first and then do the action sent to this function
alert('This function is named "abc"');
action();
}
abc(function(){alert("I like pizza")});
the bad way (if your actions need to be strings):
function abc(action)
{
//Do a bunch of stuff first and then do the action sent to this function
alert('This function is named "abc"');
eval(action);
}
abc('alert("I like pizza")');
The second way is not advised because eval causes issues. It can run arbitrary code that can cause unexpected side effects, prevents compiler optimizations, and leads to difficulty debugging (since it can literally do anything depending on what you pass it). More on why eval is bad here.
But it will run an arbitrary string as javascript code like you were asking.
You just need to instantiate a function:
abc(function() { alert("I like pizza"); });
edit and then to call it, you use the value of your parameter exactly as if it were a function name (because, well it is!):
action();
You can use the eval method:
function abc(action)
{
//Do a bunch of stuff first and then do the action sent to this function
alert('This function is named "abc"');
eval(action);
}
abc('alert("I like pizza")');
And that's that.
Don't know what JavaScript version supports this syntax but you also can try:
function abc(action) {
if (typeof(action) != 'function')
return;
action();
}
abc(() => console.log('A B C'));
Related
My question is simple. Can you call a C# webservice from the Success function of another webservice? I think that the answer is no.
I have a login webservice which is called when a user tries to do something that requires the user to be logged in. This then calls another webservice, when the action is complete it does not go into the onSuccess function. I am assuming that it is not able to do so? Is this correct?
Example code, not actual code.
webservice.login(onLoginSuccess)
function onLoginSuccess(){
webservice.doSomething(onDoSomethingSuccess)
}
function onDoSomethingSuccess(){
.... does not get here.
}
This is the code to it's bare bones.
On client JavaScript call, success of login webservice.
function onLoginSuccess(result){
negotiateWithUser(true,
activeUser.id,
negotiation.dateID,
activeUser.showChat,
true);
}
function negotiateWithUser() {
<code>
if (justLoggedIn) updateDateData();
<code>
}
function updateDateData(){
if (populate==false){
populate=true;
WebService.Negotiations.DatesGet(activeUser.id,SucceededtoCallbackDateRefresh, ErrorHandler);
}
}
Does not go into the function SucceededtoCallbackDateRefresh even though data is returned and there are no errors.
I think I know what the problem is, in the negotiateWithUser function the updateDateData is called, execution control is given back to the negotiateWithUser function instead of going into the SucceededtoCallbackDateRefresh success funtion, as it is an asynchronous call. I think some kind of callback function is required.
I have got round the problem by calling the updataDateData function in a setInterval() in the onLoginSuccess function instead.
function onLoginSuccess(result){
if (negotiate) {
timerInterval = setInterval("updateDateData()", 300);
}
}
It works. If someone has a more graceful approach, I would be very interested.
Thanks.
How about to use jQuery.ajax()?
function Func1() {
$.ajax({
url:'MyWebService.asmx/Func1',
success:Func1Success,
error: function () {
alert('there was an error!');
},
});
return false;
}
function Func1Success(output){
$.ajax({
url:'MyWebService.asmx/Func2',
success:Func1SuccessToSuccess,
error: function () {
alert('there was an error!');
},
});
}
function Func1SuccessToSuccess() {
return false;
}
You definitely can.
Just to give a suggestion/advice theoretically, you can have 1 local variable for the status response of the first web service method, you can have it as boolean, representing the success of the first invocation. Then sequentially, you can call the other web service method if your local variable matches your success condition.
What I provided is just an idea, for a more specific answer, I recommend you posting the actual code you're working on.
Thanks.
I am assuming you are using .cs files on your server and then calling them from android.
If this is what you are doing then there is one way to call a method on success of another method. Just make two .cs files say x and y and store it on your server. Then call one of them from android (x) and then make object of y in x and that will be all.
for eg. This is my one .cs file named abc.cs which il call from android.
[WebMethod]
public xyz IsLoggedIn()
{
xyz example = new xyz();
//do something
.
.
return example;
}
now xyz.cs will be:
[WebMethod]
public void onSuccessofIsLoggedIn()
{
//do something
.
.
}
i hope this helps.... All this is just based on assumption though...please be clear about what you are using and we will be also more clear in our answers.
I have two JavaScript function in two different files. On click I am calling first function to delete and second function for refresh the text in the div. The problem is delete function is having confirm action. So if I call one after the other refresh function is executing immediately. But I want refresh function to execute after confirmation (Note:delete and refresh JavaScript functions are there in two different projects)
Below is the sample:
function deleteIFAsset(a) {
var id1 = a.id;
IframeCloudEditor.deleteFileFromTimeline(id1);
refreshAsseListt();
}
You'll have to use a callback. Any properly-designed library with asynchronous operations (like waiting for the user to confirm an action in an event-driven environment like a browser) should offer a callback for when that operation is complete. You haven't said what library the deleteFileFromTimeline comes from, but hopefully it offers a callback. The callback may be an argument you pass, or it may be part of a "promise" API.
If it accepts a callback directly, that would look something like this:
function deleteIFAsset(a) {
var id1 = a.id;
IframeCloudEditor.deleteFileFromTimeline(id1, function() {
refreshAsseListt();
});
}
or
function deleteIFAsset(a) {
var id1 = a.id;
IframeCloudEditor.deleteFileFromTimeline(id1, refreshAsseListt);
}
...if your refreshAsseListt (was that supposed to be refreshAssetList?) is compatible with what the library does with the callback (the arguments it passes to it and what it does with the return value).
If it returns a promise instead, that would look something like this:
function deleteIFAsset(a) {
var id1 = a.id;
IframeCloudEditor.deleteFileFromTimeline(id1).then(refreshAsseListt);
}
("Promises" are also sometimes called "futures" or "deferred objects.")
if you can change the code of deleteFileFromTimeLine, you can change it to return the result of the confirmation.
and execute refreshAsseListt.
example
function deleteFileFromTimeLine(ID)
{
...
return Confirm('Delete File?');
}
and change your code like this
function deleteIFAsset(a) {
var id1 = a.id;
if(IframeCloudEditor.deleteFileFromTimeline(id1))
{
refreshAsseListt();
}
}
You are searching for a solution, to execute your javascript synchronous. But javascript is always executed synchronously except for special cases like ajax requests or file access.
My advice is to use a callback function to solve this problem.
Note : No jQuery
I have four functions and I want to call them one after another ie. call a function after the previously called function is executed (in core js, not jquery). I tried searching in the internet but I could not find a satisfied answer. Here is what I've done so far :
function func1() {
noAjaxCall.click();
return true;
}
function func2() {
ajaxCall.click(); <--------- sending an ajax request
return true;
}
function func3() {
noAjaxCall.click();
return true;
}
function func4() {
//anything here
}
if(func1())
if(func2())
if(func3())
func4();
What happens is that, func3 is not called. Why this happens and any work around to this?
Thanks!
I'm sure you're not doing what you expect.
The AjaxCall is not really done when func3 will be called, cause... it's asynchronous.
I prefere you find the real solution (what you really wanna do) than trying to solve this problem.
Could you give the real goal you try to achieve?
edit
Let's imagime the handle on 'click' for ajaxCall. I know u don't have jQuery on the app but I create what I know.
function requester(){
//do some asyn work
$.ajax({ //...
success: function() {
//HERE call the other functions
}
});
}
I want to save all sections, made updates to questions with IDs for the just saved sections, then save the questions, and then if that is successful fire a function nextPage that redirects the page. I'm trying to confirm this is correct. It seems to act funny if I don't have the anonymous function wrapped around saveAllQuestions.
saveAllSections(function () {saveAllQuestions(nextPage)});
Update:
On the success of saveAllSections it does the following:
if (typeof(callback) == 'function')
callback();
On the success of saveAllQuestions it does the following:
if (questionValuesToSave.length>0) {
saveAllQuestionValues(questionValuesToSave, callback);
}
else {
// once its done hide AJAX saving modal
hideModal();
if (typeof(callback) == 'function')
callback();
}
On the success of saveAllQuestionValues (assuming there are some) it does the following:
if (typeof(callback) == 'function')
callback();
Yes that is a generally correct syntax for a callback, though its hard to know for sure without seeing more code.
The following code
saveAllSections(saveAllQuestions(nextPage));
would fail because saveAllQuestions(nextPage) is the syntax to execute a function, rather than define it. So it will execute that immediately and pass the result to saveAllSections, which will try to use it as the callback. Since this is likely not a function, and almost definitely not the function you want to pass you will get strange behavior, most likely an error.
Wrapping this in an anonymous function means that you're passing a function to saveAllSections, which does not execute until it is called by the outer function or as a callback.
UPDATE:
Looks like saveAllQuestions is also async based on your description, so executing it immediately will definitely not work correctly. The anonymous function wrapper is a completely acceptable solution if you need to pass a param.
If you didn't, you could just use
saveAllSections(saveAllQuestions)
The reason you need to wrap saveAllQuestions in an anonymous function is because otherwise saveAllQuestions gets executed right away, and its return value gets passed as the callback to saveAllSections.
If you wrap saveAllQuestions in an anonymous function, you prevent saveAllQuestions from executing right away.
In javascript, you can pass a function as an argument. This allows for simpler code and asynchronous callbacks. In your attempt, you don't pass a function in. You execute a function, so the result of saveAllQuestions(nextPage) is passed into the function, not the function saveAllQuestions.
Hopefully this example helps.
function add(a,b) {
return a+b;
}
function mul(a,b) {
return a*b;
}
function doMath(num1, num2, op) {
return op(num1, num2);
}
document.write( doMath(4,5, add) ); // 9
document.write( doMath(4,5, function (n1,n2) {return n1+n2;}) ); // 9
document.write( doMath(2,5, mul) ); // 10
document.write( doMath(2,5, function (n1,n2) {return n1*n2;}) ); // 10
document.write( doMath( doMath(1,3, add) , 4, mul) ); // 16
I'm trying to build an API in JS that will perform some operations and then execute the callback that's registered in AS when it's done. Because it's an API, I am just providing a JS method signature for another developer to call in Flash. Thus, the callback name that's registered in the AS part of the code should be a parameter that's passed in to the JS API in order for JS to communicate back to Flash.
For example:
[AS3 code]
ExternalInterface.addCallback("flashCallbackName", processRequest);
ExternalInterface.call("namespace.jsFnToCall", flashCallbackName);
function processRequest(data:String):void
{
//do stuff
}
[JS code]
var namespace =
{
jsFnToCall: function(callback)
{
//Do stuff in this function and then fire the callback when done.
//getFlashMovie is just a util function that grabs the
//Flash element via the DOM; assume "flash_id"'s a global var
//Below does not work...it's what I'd be ideally be doing some how.
getFlashMovie(flash_id).callback(data);
}
};
Because the definition of the function is in AS, I can't use the window[function name] approach. The only way I can think of is to build the callback in a string and then use the eval() to execute it.
Suggestions? T.I.A.
Well, I can think of one thing I would try, and one thing that would work.
What I would try first.
getFlashMovie(flash_id)['callback'](data);
What would work: Have the callback always be the same, say callback. The first parameter to the callback could be used to determine what actual function to call in flash. For example:
function callback($fn:String, $data:*) {
// either
this[$fn]($data);
// or
switch ($fn) {
case "callback1":
DoSomeCallback($data);
break;
}
Additionally passing the objectID makes it a bit simpler:
ExternalInterface.addCallback("flashCallbackName", processRequest);
ExternalInterface.call("namespace.jsFnToCall", ExternalInterface.objectID, "flashCallbackName");
Then in your JS:
var namespace =
{
jsFnToCall: function(objectID, callback)
{
//Do stuff in this function and then fire the callback when done.
document[objectID][callback](data);
}
};