gpt4 book ai didi

javascript - 在调用之前按顺序完成所有函数参数

转载 作者:行者123 更新时间:2023-11-30 08:06:28 29 4
gpt4 key购买 nike

我正在尝试了解如何使以下 zip 函数(尤其是 invoke 函数)更具功能性。我遇到的问题是 invoke 方法必须等待左侧和右侧都被填充,然后才能分派(dispatch)值。必须按顺序调用这些值,以便压缩正确的值,否则我会考虑使用 curry/partial 函数来实现这一点。

有什么我可以使用的东西可以消除这种障碍。

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();
});
}

Bellow 是一个满足 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());

奖励:删除可变数组。

最佳答案

如果 Stream 有某种 iterator 接口(interface),将列表划分为第一个元素及其后续元素(就像 Haskell 列表是建成,你似乎认识他们)。

一开始我知道这段代码更复杂(至少更长),但使用这些结构会更方便:

function Promise(resolver) {
// you know better promise libs of course
// this one is not even monadic
var subs = [],
res = null;
resolver(function resolve() {
res = arguments;
while (subs.length) subs.shift().apply(null, res);
});
this.onData = function(f) {
if (res)
f.apply(null, res);
else
subs.push(f);
return this;
};
}
Promise.all = function() {
var ps = Array.prototype.concat.apply([], arguments);
return new Promise(function(resolve) {
var res = [],
l = ps.length;
ps.forEach(function(p, i) {
p.onData(function() {
while(res.length < arguments.length) res.push([]);
for (var j=0; j<arguments.length; j++)
res[j][i] = arguments[j];
if (--l == 0)
resolve.apply(null, res);
});
});
});
};
function Stream() {
// an asynchronous (random) list
var that = this,
interval = (Math.random() * 100 + 500) | 0;
this.first = new Promise(function create(resolve) {
that.id = setTimeout(function() {
resolve(Math.random(), new Promise(create));
}, interval);
});
}
// this is how to consume a stream:
Stream.prototype.forEach = function(f) {
this.first.onData(function fire(res, next) {
f(res);
next.onData(fire);
});
return this;
};
Stream.prototype.end = function() { clearTimeout(this.id); return this; };

但是现在压缩它们很容易:

function zip() {
var res = Object.create(Stream.prototype); // inherit the Stream interface
res.first = (function create(firsts) {
return new Promise(function(resolve) {
Promise.all(firsts).onData(function(results, nexts) {
resolve(results, create(nexts));
});
});
})(Array.prototype.map.call(arguments, function(stream) {
return stream.first;
}));
return res;
}
zip(new Stream, new Stream).forEach(console.log.bind(console));

基本上,我已经将您对第一个项目的等待概括为 Promise 模式,其中 Promise.all 具有并行等待的特点,而您的可变结果数组则概括为嵌套的 promise 列表。我通过让所有函数都使用任意数量的参数来避免代码重复(对于 leftright)。

关于javascript - 在调用之前按顺序完成所有函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17406800/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com