Javascript Callbacks with custom aguments

综合技术 2018-03-14

I am trying to work out how to implement an asynchronous callback in node given that I don't know what the arguments could be.

I'll state the sync version of what I'm trying to do so as to make this clearer.

function isAuthorized(userID){
    // check for user Permissions here
    return isAuthorized;
}

Using this any function can call it and, from the value it returns, determine if the user is authorized. However, the function that I use to get the userID (and check for permissions) are both asyncronous functions and require callbacks. However I have no idea how to get this implemented when I don't know the arguments needed in the callback.

The function that calls this could want to send an number of arguments to the callback (normally it'd just wait for a return in sync) and that's what's confusing me.

function isAuthorized(socket, callback, args){
    socket.get('userID', function (err, userID) {
        //check userID for permission
        callback(args);
    });
}

I realize I could convert the arguments into an array and send that array, but I wanted to know if there is a more general way to do this that doesn't force me to make all my callbacks convert from an array of arguments.

Hope you can help, Pluckerpluck

Problem courtesy of: Pluckerpluck

Solution

You can always create a function to pull those arguments into an array for you, and then reuse it in each of your async functions:

function asyncWithCallbackArgs(obj, callback) {
  var args = Array.prototype.slice.call(arguments, 2);
  callback.apply(obj, args);
}

This will then enable you to do things like this:

function callback (c, d, e, f) {
  console.log([c, d, e, f]);
}

asyncWithCallbackArgs({}, callback,'c','d','e','f');​

There's a fiddle here
to play with.

Solution courtesy of: rjz

Discussion

If I'm understanding you correctly, don't pass them as arguments at all:

var a = "something";
var b = "something";

var callback = function(){
   // use a and b here
};

isAuthorized(socket, callback);

http://jsfiddle.net/S4tH6/

Discussion courtesy of: James Montagne

I'm not sure, if I understand you the right way, but it seems you're looking for the arguments
object in a function ( MDN link
).

Basically that way you don't have to specify any parameters in advance, but have the function look for what parameters are present. So you can do something like the following:

function myFunc() {
  for (var i=0; i<arguments.length; ++i ) {
    console.log( arguments[i] );
  }
}

Which results in outputs like

myFunc( 1 );
> 1
myFunc( 's', 3, 'S' );
> "s"
> 3
> "S"

Discussion courtesy of: Sirko

In Coffee-script you have something called splats.

( socket, callback, args... )->

  callback args...

This translates as the following in Javascript:

var __slice = [].slice;

function() {
  var args, callback, socket;
  socket = arguments[0], callback = arguments[1], args = 3 <= arguments.length ?__slice.call(arguments, 2) : [];
  return callback.apply(null, args);
};

Discussion courtesy of: Pickels

So when you build an API, you specify what order the arguments are passed into the callback. So, you will want to comment your code well so that anyone who uses your API can understand what they will be getting back from your method.

It almost sounds like you are perhaps wanting to pass back different arguments, depending on what the passed in callback function looks like. That isn't traditionally how an API works. It would take a considerable amount of time to do that effectively.

I would recommend passing an object to the callback. The Object can have multiple arguments that people can pull out of it. This would ease future enhancement, as you could very simply add an additional property to that object without messing up everyone's implementation of your method. So, return something like this :

{
    "id": "Some_ID",
    "message": "Some Message",
    "isAuthorized" : true
}

This way anyone who uses your API doesn't have to account for multiple arguments in the callback method. They know that they are only going to get one arg, and that it will be an Obj with multiple properties, and they can consume which properties they want. Further, in the future you can add a 4th or 5th property without breaking their code. You could add a "datetime" property, and their code would remain unchanged. You would get backwards compatibility, and new implementors could then use the new properties.

Discussion courtesy of: frosty

This recipe can be found in it's original form on Stack Over Flow
.

您可能感兴趣的

Podcast: Colin EberhardtonWebAssembly A note to our readers: You asked so we have developed a set of features that allow you to reduce the noise: you canget email and web notif...
Feature Spotlight: HILITING What’s HILITING? The ‘hiliting’ system in SmartClient allows data highlighting rules to be defined to automatically surface important informat...
Using javascript develop flash Javascript and Flash in AS3 Is it possible to use Javascript in flash. For example, as a simple test I am trying to use Javascri...
Define the header of the response content type in ... I have a use case where I make a cross domain JSONP request. $.ajax({ url: "http://anyorigin.com/get/?url=&callback=?'", dataType: 'jsonp...
Why package managers need hook systems Installation hooks were introduced to pnpm in version 1.12 . In this article, I want to write about why I think package managers (PMs) need hooks. ...