Cumprindo todos os argumentos da função em ordem antes de invocar

Estou tentando entender como a seguinte função zip (especialmente a função invoke) pode se tornar mais funcional. O problema que tenho é que o método de invocação tem que esperar que ambos os lados esquerdo e direito sejam preenchidos antes que ele possa despachar os valores. Os valores devem ser chamados em ordem para que os valores corretos sejam zipados, caso contrário, eu consideraria uma função curry / partial para atender a isso.

Existe alguma coisa que eu possa usar para remover 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();
    });
}

Abaixo está um exemplo simples do que satisfaz a função 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());

Bônus: Removendo matriz mutável.

questionAnswers(3)

yourAnswerToTheQuestion