I am unable to pass two arguments to the adapter onSuccess() function using IBM Worklight. Please show me the way. Here is what I am currently trying:
var options = {
onSuccess : SubCategoriesSuccess(options, result),
onFailure : SubCategoriesFailure,
invocationContext: {}
};
The onSuccess parameter requires a reference to a function, not an invocation of a function - note that there is a difference between SubCategoriesSuccess and SubCategoriesSuccess() in JavaScript. What you are doing is passing the result of calling SubCategoriesSuccess(options, result).
What you need is what is typically referred to as partial invocation in programming jargon. JavaScript itself has a function for doing this - Function.prototype.bind(). You should probably look at that (although there alternatives provided by various JavaScript toolkits too).
This would mean your code would look something like:
{
onSuccess : SubCategoriesSuccess.bind(this, options, result),
onFailure : SubCategoriesFailure,
invocationContext: {}
};
Note that I have not tested this.
If options is a variable already on your calling function. You have to wrap the return function in another. So in other words, success is returned from the adapter, and options is just passed along by the calling function.
onSuccess:function(result){
SubCategoriesSuccess(options, result);
}
Related
I’m building a node-module wrapper for a C++ library to pass logging information through Nan to JavaScript. For this a NAN_Method is available to register a callback. The callback handler has to register itself as a callback at the C++ library via vlAddLogListener(). The LoggingCallbackHandler receives a message from the library at the function dispatchEvent, a C++ function. If I receive a log, I want to call the JavaScript callback to pass the data on.
The function dispatchEvent isn’t called in a Nan-context and therefore I don’t have a scope/context and no access to v8. How is it possible to call the JavaScript callback?
The code looks like this:
NAN_METHOD(registerLoggingCallback)
{
v8::Isolate* isolate = info.GetIsolate();
v8::Local<v8::Function> fun = info[0].As<v8::Function>();
lch = new LoggingCallbackHandler(isolate, fun);
}
LoggingCallbackHandler::LoggingCallbackHandler(v8::Isolate* isolate, v8::Local<v8::Function> fun) :
_cb(isolate, fun)
{
vlAddLogListener(&LoggingCallbackHandler::dispatchEvent, this);
}
void VL_CALLINGCONVENTION LoggingCallbackHandler::dispatchEvent(const char* eventData, void* clientData)
{
// here I want to process the data and call the JavaScript callback
v8::Local<v8::Function> f = v8::Local<v8::Function>::New(Nan::GetCurrentContext()->Global()->GetIsolate(), _cb);
Nan::MakeCallback(Nan::GetCurrentContext()->Global(), f, argc, argv);
}
Using Nan, you should save the function value using a Nan::Callback inside your registerLoggingCallback function :
Nan::Callback cb;
cb.Reset(info[0].As<v8::Function>());
Store this Nan::Callback inside your class. Modify your dispatchEvent function to use a uv_async_t to schedule a call to your callback to be run in the main thread.
The use of uv_async_t can be simplified using a Nan::AsyncWorker but you may be better off reading the documentation for a better understanding of how that works.
When you actually want to call the callback, you can do:
v8::Local<v8::Value> arg = Nan::Null();
cb.Call(1, &arg);
You can pass more values into the callback by passing an array of v8::Local<v8::Value> as the second parameter and increasing the first parameter accordingly.
How does the callback in fs.readfile get called when using fs.readfile.bind(context,pathArgument) like so. //understandable because my task function knows the name of the callback parameter
async.series([function(callback){
//operation done callback()},...],finalCallback(err,result));
BUT
//not understandable
async.series([fs.someOperation.bind(null,firstArgument),...],finalCallback(err,esult))
I believe I understand partial application;however, it would look something like this. function(callback){ fs.someOperation(firstArgument, ????)}(asyncCallbackFunc) and then I have no idea how the second argument is called...
Thx, in advance for helping me clear this up.
All bind does is set the context of the callback. It is still a regular callback like any other. Except, it is explicitly told what this will be. Looks like in your case, it is set to null.
The bind function on function object allows you to set the context i.e the value of this inside the function body as well as allow you to create a partial function in case you pass some arguments while calling bind.
For example:
function add(a,b) {
console.log(this);
return a+b;
}
var newAdd = add.bind("hello world", 10);
The newAdd will be one argument function which gets added to 10 and the result is returned. Also when newAdd is called the "hello world" will be logged in console.
Now when your code says fs.readFile.bind(null, path) it means that the return function will be of one argument which is the callback for readfile i.e the return function will be of form function(callback) { ... } which is exactly what is required to be passed to async.series
The main idea in the code you posted is to create a partial function that accepts only callback so that it can be passed to async.series the null argument doesn't play any role but you need to pass a context argument to call bind function, hence a null is passed as context arg.
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);
}
};
I'm calling PageMethod "SameMethod" from javascript method "caller" so that I can get some values from DB. After I get values, control is continuing in "onSuccess" method. Problem is that I need to use some variable values ("importantValue") from javascript method "caller" in "onSuccess" method.
function caller(){
var importantValue = 1984;
PageMethod.SomeMethod(param1,..., onSuccess, onFailure)
}
onSuccess method should be something like this:
function onSuccess(pageMethodReturnValue, importantValue ){
}
Is it possible and, if it is, how to pass multiple parameters (besides return values of page method) to "onSuccess" method of PageMethod?
Thanks for help
Pass your importantValue as an additional parameter when calling the PageMethod. (this is usually called the context parameter if you are searching online for more info)
function caller(){
var importantValue = 1984;
PageMethod.SomeMethod(param1,..., onSuccess, onFailure, importantValue)
}
Then you can access the value in the onSuccess callback as follows:
function onSuccess(pageMethodReturnValue, context, methodName){
// context == 1984
}
Update to explain onSuccess parameters for #JacksonLopes
There is a good description on the aspalliance website in an article by Suresh Kumar Goudampally
The important bit (modified to use my parameter names) is:
The success call back method has three parameters:
pageMethodReturnValue - Returns the output of the page method.
context - This is used to handle different logic when single callback is used for multiple page method requests. We can also pass
an array of values as the context parameter.
methodName - This parameter returns the name of page method called.
You could use an anonymous function
PageMethod.SomeMethod(param1,..., function(){onSuccess(foo, importantValue)}, onFailure)
I know it's maybe an fairly easy basic knowledge for you, here I need to ask your help to see whether there is a 'hole' behind to improve. Please check the code below, can I set 'response' as callback parameter but not callSvc's? instead of this kinda 'tricky' way?
function callSvc(response, callback){
callback(response);
}
callSvc("I'm a response!",function(param_response){document.write(param_response);});
Thanks..
Update
Maybe this is good enough?
function callSvc(callback) {
callback("response");
}
callSvc(function(data) {
document.write(arguments[0]);
});
There shouldn't be anything tricky about closures in javascript. They are a language feature.
You can avoid the wrapping callSvc function as well, and jump straight into this:
var response = "I'm a response"
var callback = function(){document.write(response);};
The callback function can "see" response as if you passed it as a parameter, since it forms a closure.
callback(); //I'm a response
Eh? All that code looks to be the equivalent of
document.write("I'm a response!");
So you can bypass all the methods. You can also declare an anonymous function and call it immediately, if that's what you wanted to do:
(function(param_response){document.write(param_response);})("I'm a response!");
Or lastly, if you need to pass parameters to a callback that doesn't except any, then wrap it in an anonymous funciton
func_that_takes_callback(function(){the_real_callback(arg);});
Instead of defining your callback anonymously define it before hand:
function callSvc(response, callback){
callback(response);
}
function cb(param_response) {
document.write(param_response);
}
Then you can use it in a call to callSvc or on its own:
callSvc("I'm a response!", cb);
cb("I'm a response!");