2

I am working on a library that will expose 3 methods. All three of these methods depend on another library (lets call it libA) having been loaded and that library loads asynchronously.

I could write the code to expose the methods as soon as the JS file has finished loading but then the user would have to defer execution until libA has finished.

I was hoping to, rather, expose "a version" of those 3 methods immediately while libA continues to load asynchronously in the background. Any calls to those 3 methods would get queued up until libA is done loading. And after libA is done loading those 3 methods would get replaced with the real one and the queue would be processed.

Let's say I have this:

var myLib = (function(){
    // expose 3 functions for the user to use
    return {
        "func1" : function(opts){},
        "func2" : function(opts){},
        "func3" : function(opts){}
    }
})();

This library will be loaded by the user. At the same time libA will also be loaded. It may take longer to load then mine or it may finish before mine starts.

So if the user runs myLib.func1({}) and libA has not finished loading then it should get queued up and then when libA is done it should execute. If, on the other hand, libA has finished loading then it would execute immediately.

My initial thought is to do something like this:

var myLib = (function(){
    // queue the calls
    var queue {
        "func1" : [],
        "func2" : [],
        "func3" : []
    };

    // the "temp" functions that just add them to the queue
    var ret = {
        "func1" : function(opts){ queue.func1.push(opts); },
        "func2" : function(opts){ queue.func2.push(opts); },
        "func3" : function(opts){ queue.func3.push(opts); }
    }

    // this may happen before the user users my library or after
    // if it happens before then the functions will be replaced before the user calls them and they won't need to be queued
    // if it happens after then the functions will get replaced and the queued up ones will be executed
    waitForLibAToFinish(function(){
        ret.funct1 = function(opts){alert("this is the real func1");},
        ret.funct2 = function(opts){alert("this is the real func2");},
        ret.funct3 = function(opts){alert("this is the real func3");},

        // process the queue
        for(var i = 0; i < queue.func1.length; ++i)
        {
            ret.func1(queue.func1[i]);
        }

        // repeat for func2 and func3 queue
    });

    return ret;
})();

But this just seems like a bad way to do it. Plus I'll have to have a queue for each function and call each one. There must be a way to abstract that part out so its more generic for all the methods my library exposes.

I'm open to any ideas/suggestions. I just cannot (for numerous reasons out of my control) use any 3rd party libraries like Promise or JavaScript. And, my code has to work on IE8. Trust me, I hate it more than you do.

===

I'm adding some more context/details.

I know I mention SharePoint but this is not an SP specific question.

I am building a library that offers convenience methods to simplify otherwise complicated tasks in SharePoint. All my library does is call SP libraries. The relevant SP libraries are loaded asynchronously. So one of two things needs to happen:

  • Either the user needs to wait for the relevant SP libraries to finish loading before calling any of the methods in my library
  • Or my library needs to wait for the relevant SP libraries to finish

The function SP offers to let you "queue" up your function until a relevant SP library is loaded is ExecuteOrDelayUntillScriptLoaded.

My library is currently built on the first option. I wanted to simplify the experience for the user so they don't have to check (by way of ExecuteOrDelayUntillScriptLoaded). I could change it to the 2nd way but there are reasons I don't want to.

Instead, what I was hoping to do is include 1 check in my library with ExecuteOrDelayUntillScriptLoaded that would "modify" what my library does. Before the relevant libraries are done loading my library would just queue up the calls. And after it is done loading and ExecuteOrDelayUntillScriptLoaded fires, my code would:

  • Execute everything in the queue
  • Modify each function my library exposes to directly execute and not queue
9
  • Are your methods going to have an async interface (e.g. a callback that they call when the result is ready)? You can't really queue them for later execution unless they have an async interface that provides some way for the caller to know when the results are ready. Commented Mar 23, 2017 at 4:45
  • FYI, this would be fairly trivial with promises (like the Bluebird promise library). Without promises, you will have to write your own queue and error handling that promises give you for free. Bluebird is compatible with IE8. You would just have each operation return a promise and under the covers you would either execute the operation and resolve the promise or wait for the library to finish loading and then execute the operation and resolve the promise. You would not have to build any sort of queue. Commented Mar 23, 2017 at 4:50
  • @jfriend00 Yes. One of the parameters sent to each func is a function to be called when my function is done. Commented Mar 23, 2017 at 4:55
  • 1
    @IMTheNachoMan What exactly is your definition of "3rd party library"? You don't have to load them from external servers if that is what you are concerned about. If you are forced to reinvent the wheel however, please just copy an existing wheel instead of asking us for other wheel construction approaches. Commented Mar 23, 2017 at 5:12
  • 1
    I'm pretty sure that ExecuteOrDelayUntillScriptLoaded does the check whether queuing is necessary quite efficiently. Replacing your library methods by the non-wrapped versions is possible but unlikely worth it (and can introduce a boot of other problems). Commented Mar 23, 2017 at 19:49

1 Answer 1

1

Don't do the queuing yourself. Leave the library loading and dependency resolution to the user. Just expose a function that instantiates your library, the user may call it when library A is ready and get the module with usable methods back.
There even already is a standard on how to do that: Asynchronous Module Definition. (You don't need require.js as a third-party library, you can implement the bare essentials yourself)

If the user wants (needs) to call your library methods before everything is loaded, they can always queue the premature invocations themselves in any manner they want. But usually this should not be necessary.

Sign up to request clarification or add additional context in comments.

8 Comments

Yes. That is what I have done so far. I just thought I could do abstract that part out. Just couldn't figure out an easy way to do it.
Isn't define("myLib", ["libA"], function(liba) { return {…}; }) already enough abstraction? I'm not sure what you mean.
If you absolutely need that queuing feature, and want to implement it abstractly (so that it works on every deferred module), please show us what code you are currently using for the asynchronous dependency management. And tell us how you want to deal with return values from queued calls.
Isn't define part of RequireJS which is a library, right? And I have no code for asynchronous dependency management. The code example I gave above is a good succulent example of what I have. Queued calls won't return anything, they will call an onComplete function.
define is just a standard interface, you can implement the function yourself or deploy a library (like Require.js) that provides it. With "asynchronous dependency management" I meant your waitForLibAToFinish function - please show us what it does, where/when/how it is defined, how libA interacts with it, and what abstractions it uses. Do you also have a waitForMyLibToFinish function? If no, why not, what makes it different from libA?
|

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.