zoukankan      html  css  js  c++  java
  • [Functional Programming] Use the Callback and Closure Pattern to Build Advanced Async Behaviors [Full code]

    import { curry, compose, toUpper, pipe } from 'ramda';
    
    // #region listeners
    const _log = (value) => console.log(value);
    // #endregion
    
    // #region broadcasters
    const done = Symbol('done');
    const addListener = curry((element, eventType, listener) => {
      return element.addEventListener(evenType, listener);
    });
    const createInterval = curry((time, listener) => {
      let i = 0;
      const id = setInterval(() => {
        listener(i++);
      }, time);
      return () => {
        clearInterval(id);
      };
    });
    const createForOf = curry((iterator, listener) => {
      const id = setTimeout(() => {
        for (let item of iterator) {
          listener(item);
        }
        listener(done);
      }, 0);
      return () => {
        clearTimeout(id);
      };
    });
    const createZipOf = curry((broadcaster1, broadcaster2, listener) => {
      let cancelBoth;
      let buffer1 = [];
      const cancel1 = broadcaster1((value) => {
        buffer1.push(value);
        if (buffer2.length) {
          listener([buffer1.shift(), buffer2.shift()]);
          if (buffer1[0] === done || buffer2[0] === done) {
            listener(done);
            cancelBoth();
          }
        }
      });
    
      let buffer2 = [];
      const cancel2 = broadcaster2((value) => {
        buffer2.push(value);
        if (buffer1.length) {
          listener([buffer1.shift(), buffer2.shift()]);
          if (buffer1[0] === done || buffer2[0] === done) {
            listener(done);
            cancelBoth();
          }
        }
      });
      cancelBoth = () => {
        cancel1();
        cancel2();
      };
      return cancelBoth;
    });
    // #endregion
    
    // #region operators
    const createOperator = curry((operator, broadcaster, listener) => {
      // new a new broadcaster and invoke original broadcaster inside new broadcaster
      return operator((behaviorListener) => {
        // override the default broadcaster
          return broadcaster(value => {
            // apply common logic
            if(value === done) {
              // stop outer listen to continue emitting values
              listener(done)
              return
            }
            // otherwise, we want to pass forward the value to listener
            behaviorListener(value)
          })
      }, listener)
    })
    
    const concat = createOperator((broadcaster, listener) => {
      let string = '';
      return broadcaster((value) => {
        listener((string += value));
      });
    });
    
    const map = transform => createOperator((broadcaster, listener) => {
      return broadcaster((value) => {
        listener(transform(value));
      });
    });
    
    const filter = predicator => createOperator((broadcaster, listener) => {
      return broadcaster((value) => {
        if (predicator(value)) {
          listener(value);
        }
      });
    });
    
    const split = splitter => curry((broadcaster, listener) => {
      let buffer = []
      return broadcaster((value) => {
        if (value === done) {
          listener(buffer)
          listener(done)
          buffer = []
        }
        if (value === splitter) {
          listener(buffer)
          buffer = []
        } else {
          buffer.push(value)
        }
      })
    })
    // #endregion
    const transform =  pipe(
        map((x) => x[1]),
        filter((x) => x !== ','),
        map(toUpper),
        split(" ")
      );
    let typeGreeting = transform(
      createZipOf(createInterval(100), createForOf('My Zipo'))
    );
    const cancelGreating = typeGreeting((value => {
      if(value === done) {
        _log("Shut down")
        return
      }
      _log(value)
    }))
    // cancelGreating()
    
    const myZip = (boradcaster1, boradcaster2) => (...operators) => {
      return pipe(...operators)(createZipOf(boradcaster1, boradcaster2))
    }
     
    const typeGreeting2 = myZip(
      // boradcasters
     createInterval(100), createForOf('My Zipo')
    )(
     // operators
        map((x) => x[1]),
        filter((x) => x !== ','),
        concat,
        map(toUpper)
    )
    const cancelGreating2 = typeGreeting2(_log)
    // cancelGreating2()
  • 相关阅读:
    【Android Developers Training】 73. 布局变化的动画
    【Android Developers Training】 72. 缩放一个视图
    【Android Developers Training】 71. 显示翻牌动画
    svn更改地址怎么办
    python学习手册
    failed to bind pixmap to texture
    Ubuntu 12.04安装Google Chrome
    svn update 时总是提示 Password for '默认密钥' GNOME keyring: 输入密码
    重设SVN 的GNOME keyring [(null)] 的密码
    Nginx + uWSGI + web.py 搭建示例
  • 原文地址:https://www.cnblogs.com/Answer1215/p/13875584.html
Copyright © 2011-2022 走看看