Let's say that we have two functions and we want to call them one after each other. They both operate with same variable. The first one sets its value and the second one uses it.
So, if we now run A();B(); we will get undefined in the console. It's like that because the A function sets the value asynchronously. What we could do is to send a callback and execute it once the job is done.
This works, but imagine what will happen if we need to run five or more methods. Passing callbacks all the time will lead to messy and unpleasant code.
So, what we have to do is to run that function by passing the both A and B - queue([A, B]). We need to get the first function and execute it.
If you run this code you will see an error TypeError: undefined is not a function. That's because A function doesn't accept callback but it tries to run it. Let's pass one.
The next method is getting called once A finishes its job. That's the perfect place for continuing to the next function in the list. We could arrange the code a bit and we are able to go through the whole array.
If we leave the things like that we will reach our goal. I.e. function A is called and just after that B, which prints the correct value of the variable. The key moment here is the usage of shift method. It removes the first element of the array and returns the element. Step by step funcs array becomes empty. So, this could lead to an error. To prove this theory, let's assume that we still need to run the both functions, but we don't know their order. In this case, they both should accept callback and execute it.
And of course we got TypeError: undefined is not a function. To prevent this we should check if the funcs array is empty.
What I did also is to invoke the next function just after its definition. It saves few bytes.
Let's try to cover as many cases as possible. What about the current scope of the executed functions. The this keyword inside the functions probably points the global window object. It will be cool if we set our own scope.
We added one more parameter to the tiny library. Later instead of f(next) we use the apply function, set the scope and pass next as a parameter. Pretty much the same thing.
And here is the full example which demonstrates all the features of the library.