迭代器 -> 生成器

ES6 写法

写一个 generator 生成器 -> 调用后生成一个 迭代器 iterator

function * test(arr) {
	for (const value of arr) {
  	yield value;
  }
}

const iterator = test([1,2,3]);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

Untitled

ES5 写法

function generator(arr) {
	let nextIdx = 0,
      len = arr.length;
  
  return {
  	next() {
    	return nextIdx < len
      	? { value: arr[nextIdx++], done: false }
      	: { value: undefined, done: true }
    }
  }
}

const iterator = generator([1,2,3]);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());

⭐️ 中间件为啥最后每次要执行 next()

Untitled

为的是能够进一步执行后边中间件的逻辑,一旦当前中间件走不通,就不调用 next,从而阻断继续执行后续代码

;((functions) => {
  function * generator(arr) {
    for (let i = 0; i < arr.length; i++) {
      yield arr[i];
    }
  }

  const iterator = generator(functions);

  const init = () => {
    nextDo(iterator.next());
  }

  function nextDo(n) {
    n.value(function() { // 第一次迭代时,test1接收的参数next就是此处的匿名函数
      const n = iterator.next();
      if (!n.done) {
        nextDo(n);
      } else {
        return;
      }
    });
  }

  init();
})([
  function test1(next) {
    console.log('test1');
    console.log(next); //这里的next就是上边 n.value 中的匿名函数
    next();
  },
  function test2(next) {
    console.log('test2');
    next();
  },
  function test3(next) {
    console.log('test3');
    next();
  },
  function test4(next) {
    console.log('test4');
    next();
  },
  function test5(next) {
    console.log('test5');
    next();
  },
]);

Untitled

随时暂停中间件执行 - 类似于安检

;((functions) => {
  function * generator(arr) {
    for (let i = 0; i < arr.length; i++) {
      const func = arr[i];
      yield func;
    }
  }

  const iterator = generator(functions);

  const init = () => {
    nextDo(iterator.next());
  }

  function nextDo(n) {
    n.value(function() { // 第一次迭代时,test1接收的参数next就是此处的匿名函数
      const n = iterator.next();
      if (!n.done) {
        nextDo(n);
      } else {
        return;
      }
    });
  }

  init();
})([
  function test1(next) {
    console.log('test1');
    let username = '233'
    if (username.length > 6) {
      next();
    }
  },
  function test2(next) {
    console.log('test2');
    next();
  },
  function test3(next) {
    console.log('test3');
    next();
  },
  function test4(next) {
    console.log('test4');
    next();
  },
  function test5(next) {
    console.log('test5');
    next();
  },
]);

Untitled

demo

Untitled

应用

日志打印

;(function(doc) {
  function Log() {
    this.oInput = doc.getElementsByTagName("input")[0];
    this.oBtn = doc.getElementsByTagName("button")[0];
    this.oList = doc.getElementsByClassName("logs")[0];
    this.logs = [];
    this.iterator = generator(this.logs);
    this.init();
  }

  Log.prototype.init = function() {
    this.bindEvent();
  }

  Log.prototype.bindEvent = function() {
    this.oBtn.addEventListener('click', handleBtnClick.bind(this), false);
  }

  function handleBtnClick(e) {
    const val = this.oInput.value;
    this.logs.push({
      date: new Date(),
      value: val,
    })

    _addLog.call(this, this.iterator.next().value);
  }

  function _addLog(log) {
    const oLi = doc.createElement("li");
    oLi.innerHTML = `
      操作内容: ${log.value}
      操作时间: ${log.date}
    `;

    this.oList.appendChild(oLi);
  }

  function * generator(arr) {
    for (const value of arr) {
      yield value;
    }
  }

  window.Log = Log;
})(document);