简体   繁体   中英

Modifying number of arguments for callback functions - javascript

I know many of you already used JavaScript UI widget plugins, etc... that offers callback functions. For instance we have Object x and it has a function, let say .doThisAfterAnEvent() . And according to the official documentation of Object x , that function accepts a single parameter of type function() with one argument, let say _args .

To visualize, here is the example:

var handler = function(_args) {
    // Do something.
}

var x = $("#element-to-widget-ify").transform()
x.doThisAfterAnEvent(handler)

My question is, how can I modify the method .doThisAfterAnEvent() to accept a function with two or more parameters instead of one? In this case, I need to pass a second extra value to the handler function.


Edit:

var widgets = {
    "widget-at-the-nav": $("#nav-widget").transform(),
    "widget-at-the-footer": $("#nav-footer").transform(),
    "widget-at-the-search": $("#nav-search").transform(),
    length: 3
}

var handler = function(_args, _option) {
    console.log("key in: " + _option
    // Other processes...
}

for(key in widgets) {
    console.log("key outer: " + key)
    widget[key].doThisAfterAnEvent(function(json) {
        console.log("key out: " + key)
        handler(json, key)
    })
}

This is my attempt. But it prints like this:

key outer: widget-at-the-nav
key outer: widget-at-the-footer
key outer: widget-at-the-search
key out: widget-at-the-nav
key in: widget-at-the-nav
key out: widget-at-the-nav
key in: widget-at-the-nav
key out: widget-at-the-nav
key in: widget-at-the-nav

And I forgot to tell you guys that the function .doThisAfterAnEvent() (not the handler() function) has an AJAX call inside.

If you ask that, I guess you mean at the moment you call doThisAfterAnEvent, you already know one parameter over two for your handler.

In this case, the solution is too wrap your handler with two parameter in a anonymous function that only take one parameter and then call back your handler :

x.doThisAfterAnEvent(function(_arg) { handler(myKnownArg, _arg) });

This question is a mess, so I'm only going to touch on the most recent edit, and the code it contains.

Your approach with masking the handler with an anonymous function is pretty much correct, it's just that your loop is messing up your lexical scope. The AJAX bit is a very important detail, because any AJAX calls are most likely going to operate long after you've looped, which means those callback functions will all reference the same final value of key .

You need to create a new scope where the key is 'locked in', so that the references are correct.

 function Con () {} Con.prototype.doThisAfterAnEvent = function (fn) { // Fake some AJAX programming window.setTimeout(function () { fn.call(this); }, 1500); }; $.fn.transform = function () { return new Con(); }; var widgets = { "widget-at-the-nav": $("#nav-widget").transform(), "widget-at-the-footer": $("#nav-footer").transform(), "widget-at-the-search": $("#nav-search").transform() }; var handler = function(_args, _option) { console.log("key in: " + _option); // Other processes... }; for (var key in widgets) { console.log("key outer: " + key); (function (key) { // Use an IIFE to establish a new lexical scope widgets[key].doThisAfterAnEvent(function(json) { console.log("key out: " + key); handler(json, key); }); }(key)); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 

In ES6 , we'd use let .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM