Создайте конвейер из Json в потоки с помощью transducers-js и most.js

У меня есть этот модуль Amd

define(function (require, exports, module) {
'use strict';
var t = require("transducers");
var most = require("most");

var groupby = function (prev, curr) {
       var key = curr.type;
       if (!prev[key]) {
             prev[key] = [curr];
       } else {
            prev[key].push(curr);
       }
       return prev;
};
function category(kv) {
     return {
           type: kv[0],
           label: kv[1][0].label,
           counter: kv[1].length
     }
  }
  function dom(cat) {
       var el = document.createElement("li");
       el.innerHTML = cat.label;
       return el;
  }

function append(prev, curr) {
        prev.appendChild(curr);
        return prev;
 }

function createClick(prev, curr) {
     return prev.merge(most.fromEvent("click", curr)
      .map(function (e) {
            return e.currentTarget.innerHTML;
      })
    )
 }

var xf = t.comp(
                 t.map(category),
                 t.map(dom)
               );

module.exports = {
         main: function (data) {

               var groups = t.reduce(groupby, {}, data);
               var container = t.transduce(xf, append, document.querySelector("ul"), groups);
               var streams = t.reduce(createClick, most.empty(), [].slice.call(container.querySelectorAll("li"), 0));

              streams.forEach(function (e) {
                   console.log("click", e);
               });
        }
     };
});

Основная функция берет список элементов, затем группирует их по свойству type. После этого он создает и добавляет элементы

  • . Наконец это создает поток кликов. Я новичок в области реактивного программирования и преобразователей.

    Но мне было интересно, найдется ли способ создать конвейер.

    Я беспокоюсь, потому что групповой режим является сокращением и не может составить его в преобразователе. Я уверен, что что-то упустил. Спасибо

  • 1 ответ

    Решение

    Попробуйте разделить вашу проблему на вещи, которые могут воздействовать на отдельный элемент в сравнении с коллекцией, и подождите до последнего, чтобы уменьшить их. также проверьте часто пропущенную операцию "сканирования", которая может спасти вас от чрезмерного сокращения

    В вашем примере у вас есть 3 возможных сокращения операций: - объединить все потоки кликов в один поток событий - объединить все dom в один счетчик ul - count

    Все это может быть выполнено с помощью сканирования, но проблема возникает в том, что вы хотите уникальные категории, но вы также учитываете не уникальные категории. Из вашего примера не ясно, является ли это требованием, хотя...

    Поскольку большинство уже работает подобно преобразователям, они вам на самом деле не нужны. В этом примере я остановлюсь на чистых мостах;

    var most = require("most");
    
    function gel(tag) {
        return document.createElement(tag);
    }
    
    var cache = Object.create(null);
    
    function main(dataArray) {
        most.from(dataArray)
    //only pass along unique items to represent categories
    //optionally, also count...
            .filter(function uniq(item) {
                var category = item.type;
                if (!(category in cache))
                    cache[category] = 0;
                cache[category]++;
                return cache[category] == 1;
            })
    //transform
            .map(function makeLI(item) {
                var li = gel("li");
                li.innerHTML = item.label;
                item.dom = li;
            })
    //attach click handler
            .map(function (item) {
                item.click = most
                    .fromEvent("click", item.dom)
                    .map(function(e) {
                        item.label;
                    });
                return item;
            })
    // merge
            .scan(function mergeIn(all, item) {
                el.appendChild(item.dom);
                clicks.merge(item.click);
            }, { ul: gel("ul"), clicks: most.empty() })
    //force stream init b creating a demand
            .drain()
    //most resolve stream into promises, but we could have just 
    //as easily used reduce here instead
            .then(function onComplete(all) {
                all.clicks.forEach(function(msg) {
                    console.log("click", e);
                })
            })
    }
    

    возможны дальнейшие изменения. например, если мы хотим добавить подсписок для каждого элемента категории, мы могли бы присоединить поток к объекту контекста для каждой категории и постепенно добавлять к каждому дочернему элементу по мере продвижения

    Другие вопросы по тегам