6

Is there a descent way to wrap all methods in an existing javascript object(for example third party library) with try catch so that I can process the exeception errors? Sure, I will expose the methods under a new interface.

Here is what I have in mind for now:(consider it as pseudocode)

var MyInterface = {};
for (var property in thirdPartyLib) {
  if ((typeof thirdPartyLib[property]) === 'function'){
    MyInterfac[property] = function(){
      try {
        thirdPartyLib[property](arguments)
      }
      catch(err){
         //do my custom processing
      }
    }
  }   
}

//developer use MyInterface object

Just wondering, any better approach or any flaw with my above idea? Thanks.

1
  • (typeof thirdPartyLib[property]) does not need to be wrapped in parenthesis. Commented Dec 18, 2015 at 0:54

1 Answer 1

4

Almost! The only issue is that you aren't passing the arguments correctly. arguments is a pseudo-array object that contains all of the arguments passed into the function call. What will end up happening with your code as-is, is that the real function would get called with a single object, rather than the individual arguments you received in your wrapper function.

What you can also do is use a closure to just do an in-place wrapping so you don't need to worry about using a different object.

function safeWrap(service, fn) {
    var ogFn = service[fn];
    service[fn] = function () {
       try { return ogFn.apply(service, arguments); }
       catch (err) {
           // doh.
       }
    };  
}

function wrapObj(service) {    
    for (var fn in thirdPartyLib) {
        var type = typeof(thirdPartyLib[fn]);
        if (type === 'function') {
            safeWrap(thirdPartyLib, fn);
        } else if (type === 'object') {
            wrapObj(thirdPartyLib[fn]);
        }
    }
}

wrapObj(thirdPartyLib);

Edited to make the wrapping recursive, per @RobG's suggestion

If performance is an issue, you can manually pass the arguments to avoid the perf hit of using Function.apply:

function safeWrap(service, fn) {
    var ogFn = service[fn];
    service[fn] = function (a, b, c, d, e, f, g, h, i, j, k, l) {
       if (arguments.length > 12) {
           console.error('Time to add %s more args!', arguments.length - 12);
       }
       try { return ogFn.call(service, a, b, c, d, e, f, g, h, i, j, k, l); }
       catch (err) {
           // doh.
       }
    };  
}
Sign up to request clarification or add additional context in comments.

3 Comments

That's kind of a shallow wrap. ;-) It should be recursive, since many libraries have methods more than one object deep, e.g. myLib.dom.getElement(). Any estimate of the performance hit of this?
Whups, good point! Updated to make it recursive. I wouldn't expect the initial setup to have a big perf hit since it only has to do it once. Here's a question about try/catch perf: stackoverflow.com/questions/19727905/… ... but it looks like the primary risk would be using apply() vs a direct function call: stackoverflow.com/questions/8184466/…. If the max possible perf is a concern, you can always pass the arguments through manually.
Thanks! Working like a charm!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.