3

That's a general question about using setImmediate (or another similar solutions) for API purpose. I'm writing a node.js library which performs negotiation with a server behind the scene. A client code of this library seems like that:

var request = myLib
    .createRequest()
    .setRequestProperty('someProperty', someValue)
    .setAnotherRequestProperty('anotherProperty', anotherValue)
    .performRequest(function callback() {
         var someValue = request.someValue;
         var requestResult = request.result;
         // Some logic based on requestResult and someValue
    });

The problem begins when my library does not need to perform or wait to any negotiation with server, thus may call the callback passed to performRequest immediately. The internal library code may then seems like:

Request.prototype.performRequest = function performRequest(callback) {
    if (this._canPerformImmediately()) {
        callback();
        return this;
    }

    this._performServerRequest().then(callback);
    return this;
};

What happens then is that request is still undefined (as the call to the callback is done before the external statement contains the request assignment is finished).

I wonder what is the correct way to define the API in such cases. I see some possibilities:

  1. Define that the callback may be called synchronously (as described above), and thus the client code may not use the request variable as in the above client code example. However I've seen some code that seems as above, so I guess this is not the solution.
  2. Define that the callback may be called synchronously, and that the request is also passed to the callback so the client code may be (Notice the use of request_ instead of request):

    .performRequest(function callback(request_) {
        var someValue = request_.someValue;
        var someResult = request_.result;
        // Some logic based on requestResult and someValue
    }
    

    (EDIT: The request may be also passed as this argument).

    But again, as I've seen some code that seems as the first example, I guess this is also not the solution.

  3. Guarantee that the callback is called ASYNCHRONOUSLY. Then we can use setImmediate functions. The internal implementation then will look like (Notice the setImmediate call):

    Request.prototype.performRequest = function performRequest(callback) {
        if (this._canPerformImmediately()) {
            setImmediate(callback);
            return this;
        }
    
        this._performServerRequest().then(callback);
        return this;
    };
    
  4. Any other suggestions?

It seems that the setImmediate alternative is the most attractive, but I failed to find discussion about using it for API consideration only. I've seen discussions about performance such as here and here, but no API considerations.

So my question is: What is the correct way to implement such library?

Community
  • 1
  • 1
MaMazav
  • 1,773
  • 3
  • 19
  • 33
  • 1
    I'd personally go with the 3rd. Because: 1. it lets API consumer be unaware of the internals 2. Promises A+ solves similar problems in similar way (requirement of asynchronicity) 3. There are libraries which make use of setImmediate to allow more liberal construct of the way they are invoked (example: https://www.npmjs.com/package/request) – Kuba Wyrostek Jul 10 '15 at 09:15

0 Answers0