简体   繁体   中英

What is the correct way of passing a callback?

I am writing my code as follows:

var MyLib = (function (window, $, undefined) {
    return {
        URI: 'http://testpage/API/',
        OnSuccess: function (data, status) { },
        OnError: function (request, status, error) { },
        MakeRequest: function (method, args) {
            $.ajax({
                type: 'POST',
                url: this.URI + '/' + method,
                contentType: 'application/json; charset=utf-8',
                data: args,
                dataType: 'json',
                success: this.OnSuccess,
                error: this.OnError
            });
        },
        GetSamples: function (data1, data2) {
            var args = {
                data1: data1,
                data2: data2
            };
            this.MakeRequest('GetTestData', JSON.stringify(args));
        }
   };
} (this, jQuery));

So that if I want to invoke the AJAX call, I would do:

function OnSuccess(data, status) {
   // ...
}

function OnError(request, status, error) {

}

MyLib.OnSuccess = OnSuccess;
MyLib.OnError = OnError;
MyLib.GetSamples("data1", "data2");

I don't want to change the signature of GetSamples and therefore I have chosen to implement it as above. Any suggestions on whether this is an acceptable approach (or how to improve this)?

Not very javascript idiomatic. Looks more like .NET code. The standard way to provide callbacks in javascript is to pass them as arguments. But if you cannot modify the signature of the GetSamples method then I guess this approach could also work in your situation. I just wouldn't generalize it to all your APIs. Only use as a workaround in this particular situation.

You could also return the jQuery AJAX object and invoke .done() on it where you consume the request.

Like:

var MyLib = (function (window, $, undefined) {
    return {
        URI: 'http://testpage/API/',
        OnSuccess: function (data, status) { },
        OnError: function (request, status, error) { },
        MakeRequest: function (method, args) {
            return $.ajax({
                type: 'POST',
                url: this.URI + '/' + method,
                contentType: 'application/json; charset=utf-8',
                data: args,
                dataType: 'json'
            });
        },
        GetSamples: function (data1, data2) {
            var args = {
                data1: data1,
                data2: data2
            };
            return this.MakeRequest('GetTestData', JSON.stringify(args));
        }
   };
} (this, jQuery));

And then:

function OnSuccess(data, status) {
   // ...
}

function OnError(request, status, error) {

}

MyLib.GetSamples("data1", "data2").done(OnSuccess).fail(OnError);

These are called jQuery deferreds, take a look at the API . IMO it's a very clean way to work with async calls.

I'll agree with Darin Dimitrov and will suggest to use only one callback. Not two for success and failure. For example:

MyLib.GetSamples("data1", "data2", function(err, response) {

});

By using this approach you are dealing with only one callback and you will be sure that the developers that are going to use your class will not forget to check for errors (that's the idea to put the err attribute on first place).

Interesting topic. I see a lot of JavaScript developers do things like this:

(function ($, window, document) {

  "use strict";

  var App = (function () {

    function App() {
      this.url = 'http://testpage/API';
      this.debug();
    }

    App.prototype = {

      url: 'http://testpage/API',

      success: function (data, status) {},

      error: function (req, status, err) {},

      request: function (command, options) {
        $.get({
          type: 'POST',
          url: this.url + '/' + command,
          contentType: 'application/json; charset=utf-8',
          data: options || {},
          success: this.success,
          error: this.error
        });
      },

      getSample: function (data1, data2) {
        this.request('getTestData', JSON.stringify({
          data1: data1, data2: data2
        }));
      }


    };

    return App;

  })();


})(jQuery, window, document);

I'm guessing the prototypal approach is used so that if you need your app to have multiple instances in a page, you don't have to re-define the methods.

Also one thing to note is that in JavaScript, the dominant naming convention is camelCase. A colleague of mine wrote a list of patterns in Backbone.js which applies to JS design patterns as well. http://ricostacruz.com/backbone-patterns/

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