ES6 async/generators

Date: 2018-11-19

Source: https://www.promisejs.org/generators/

// Example usage
var login = async(function* (username, password, session) {
  var user = yield getUser(username);
  var hash = yield crypto.hashAsync(password + user.salt);
  if (user.hash !== hash) {
    throw new Error('Incorrect password');
  }
  session.setUser(user);
});

// async implementation
function async(makeGenerator){
  return function () {
    var generator = makeGenerator.apply(this, arguments);

    function handle(result){
      // result => { done: [Boolean], value: [Object] }
      if (result.done) return Promise.resolve(result.value);

      return Promise.resolve(result.value).then(function (res){
        return handle(generator.next(res));
      }, function (err){
        return handle(generator.throw(err));
      });
    }

    try {
      return handle(generator.next());
    } catch (ex) {
      return Promise.reject(ex);
    }
  }
}
// Convert array to generator
function* iterator(iterable) {
	for(const item of iterable)
		yield item;
}
// Convert generator (iterator) to array
Array.from(iterator([1,2,3]));

Lazy evaluation

Source: https://codepen.io/jasonmcaffee/pen/ZEpeQBq?editors=0010

(_ => {
async function main(){
  const l = lazy([1, 2, 3, 5, 6, 7, 8])
    .filter(x => x % 2 === 0)
    .map(x => x * x)
    .filter(x => x === 4)
    .map(x => x + 1)
    .take(1);
  
  for(let x of l){
    console.log(`x: `, x);
  } 
}

function* take(iter, count){
  for (const x of iter){
    if(count-- <= 0){ return; }
    yield x;
  }
}

function* map(iter, func){
  for (const x of iter){
    console.log(`map called`);
    yield func(x);
  }
}

function* filter(iter, filterFunc){
  for (const x of iter){
    if(filterFunc(x)){
      console.log(`filter called`);
      yield x;
    }
  }
}

function* allOf(iter){
  for(let x of iter){
    yield x;
  }
}

function lazy(arr){
  const api = {
    previousGenerator: allOf(arr),
    map(mapFunc){
      this.previousGenerator = map(this.previousGenerator, mapFunc);
      return this;
    },
    filter(filterFunc){
      this.previousGenerator = filter(this.previousGenerator, filterFunc);
      return this;
    },
    take(count){
      this.previousGenerator = take(this.previousGenerator, count);
      return this;
    },
    collect(){
      return [...this.previousGenerator];
    },
    [Symbol.iterator]() { 
      return this.previousGenerator;
    },
  };
  return api;
}

main();
})();
16310cookie-checkES6 async/generators