Предположим, что у меня есть два возможно бесконечных потока:
s1 = a..b..c..d..e...
s2 = 1.2.3.4.5.6.7...
Я хочу объединить потоки, а затем сопоставить объединенный поток с медленным асинхронным действием (например, в Bacon с fromPromise
и flatMapConcat
).
Я могу объединить их с merge
:
me = a12b3.c45d6.7e...
И затем карта
s1 = a..b..c..d..e...
s2 = 1.2.3.4.5.6.7...
me = a12b3.c45d6.7e...
mm = a..1..2..b..3..c..4..5..
Как вы видите, greedier s2
потоки получат преимущество в долгосрочной перспективе. Это нежелательное поведение.
Поведение слияния не в порядке, так как я хочу иметь какое-то противодавление, чтобы иметь более чередующееся, "справедливое", "круговое" слияние. Несколько примеров поведения желаемого:
s1 = a.....b..............c...
s2 = ..1.2.3..................
mm = a...1...b...2...3....c...
s1 = a.........b..........c...
s2 = ..1.2.3..................
mm = a...1...2...b...3....c...
Один из способов подумать, что s1
и s2
отправляют задачи работнику, который может обрабатывать только одну задачу в то время. С merge
и flatMapConcat
я получу жадный диспетчер задач, но я хочу более справедливый.
Я бы хотел найти простое и элегантное решение. Было бы неплохо, если бы он был легко обобщен для произвольного количества потоков:
// roundRobinPromiseMap(streams: [Stream a], f: a -> Promise b): Stream b
var mm = roundRobinPromiseMap([s1, s2], slowAsyncFunc);
Решение с использованием RxJS или другой библиотеки Rx тоже отлично.
Разъяснения
Не zipAsArray
Я не хочу:
function roundRobinPromiseMap(streams, f) {
return Bacon.zipAsArray.apply(null, streams)
.flatMap(Bacon.fromArray)
.flatMapConcat(function (x) {
return Bacon.fromPromise(f(x));
});
}
Сравните примерную мраморную диаграмму:
s1 = a.....b..............c.......
s2 = ..1.2.3......................
mm = a...1...b...2...3....c....... // wanted
zip = a...1...b...2........c...3... // zipAsArray based
Да Я столкнулся с проблемами буферизации
... но так же я буду с несправедливым несправедливым:
function greedyPromiseMap(streams, f) {
Bacon.mergeAll(streams).flatMapConcat(function (x) {
return Bacon.fromPromise(f(x));
});
}
Мраморная диаграмма
s1 = a.........b..........c...
s2 = ..1.2.3..................
mm = a...1...2...b...3....c...
merge = a...1...2...3...b....c...