Cumpliendo todos los argumentos de función en orden antes de invocar

Estoy tratando de entender cómo la siguiente función zip (especialmente la función invocar) puede hacerse más funcional. El problema que tengo es que el método de invocación tiene que esperar a que tanto el lado izquierdo como el derecho se llenen antes de poder enviar los valores. Los valores se deben llamar en orden para que los valores correctos estén comprimidos, de lo contrario consideraría una función curry / parcial para cumplir con esto.

¿Hay algo que pueda usar que pueda eliminar este impedimento?

function zip(state, a, b) {
    var left = [];
    var right = [];

    function invoke() {
        if (left.length > 0 && right.length > 0) {
            state([left.shift(), right.shift()]);
        }
    }

    a.foreach(function(v) {
        left.push(v);
        invoke();
    });

    b.foreach(function(v) {
        right.push(v);
        invoke();
    });
}

A continuación se muestra un ejemplo simple de lo que satisface la función zip.

function Stream() {
    var env = this;
    env.subs = [];
    env.id = setInterval(function() {
        env.subs.forEach(function(f) {
            f(Math.random()); 
        });
    }, ((Math.random() * 100) + 500) | 0);
}
Stream.prototype.foreach = function(f) {
    this.subs.push(f);
}
zip(function(v) {
    console.log(v);
}, new Stream(), new Stream());

Bonus: Eliminando matriz mutable.

Respuestas a la pregunta(3)

Su respuesta a la pregunta