根本不常用知识之Generator
function isPromise(obj: any) { return typeof obj.then === "function"; } function isGenerator(obj: any) { return typeof obj.next === "function" && typeof obj.throw === "function"; } function isGeneratorFunction(obj: any) { const { constructor } = obj; if (!constructor) return false; if ([constructor.name, constructor.displayName].includes("GeneratorFunction")) return true; return isGenerator(constructor.prototype); } //上面三个是co库原生的校验 export default function co(gen) { return new Promise((resolve, _reject) => { typeof gen === "function" && (gen = gen()); function next(data) { const ret = gen.next(data); if (ret.done) return resolve(ret.value); toPromise(ret.value).then(next); } function toPromise(obj) { if (isPromise(obj)) return obj; if (isGeneratorFunction(obj) || isGenerator(obj)) return co(obj); // if (other types) {} return; // error } next(); }); }
function* gen() {} const gObj = gen(); gObj.next(); gObj.return();
Object.getPrototypeOf(gen).constructor // GeneratorFunction {prototype: Generator, ...}
const GeneratorFunction = Object.getPrototypeOf(gen).constructor;
const gen = new GeneratorFunction('a', 'yield a * 2');
class GeneratorFunction {} // GeneratorFunction 的 prototype 很通用,单独拎出来 class GeneratorFunctionPrototype { static [Symbol.toStringTag] = "GeneratorFunction"; // 实现 iterator protocol next(args) {} return(args) {} throw(args) {} // 实现 iterable protocol [Symbol.iterator]() { return this; } } // 相互引用 GeneratorFunctionPrototype.constructor = GeneratorFunction; GeneratorFunction.prototype = GeneratorFunctionPrototype; // 作用不大,设置 prototype 即可 //class Generator {} //Generator.prototype = GeneratorFunctionPrototype.prototype;
async function a() {} function* b() {} // babel 编译后 function asyncGeneratorStep(gen, resolve, reject, _next, ...) { // 调用 gen 的 next 或 throw 方法 var info = gen[key](arg); var value = info.value; if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { return new Promise(function (resolve, reject) { // 获取 generator 对象 var gen = fn.apply(self, arguments); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } // 初始化执行 next _next(undefined); }); }; }
以下代码基本都是babel的简写或粘贴过来的直接看babel编译过的也一样
let num = 0; async function gen() { num = num + (await wait(10)); // num = (await wait(10)) + num; await foo(); return num; } async function foo() { await "wangshun"; } (async () => { // debugger; await gen(); console.log("ws: res", num); })();
function _callee$(_context) { while (1) { switch (_context.next) { case 0: // await wait(10) _context.next = 3; return wait(10); case 3: // await 123 _context.next = 7; return 123; case 7: _context.next = 9; // await foo() return foo(); case "end": return _context.stop(); } } }
function _foo() { _foo = _asyncToGenerator( regeneratorRuntime.mark(function _callee2() { return regeneratorRuntime.wrap(function _callee2$(_context2) { switch (_context2.next) { case 0: _context2.next = 2; return "literal"; case "end": return _context2.stop(); } }, _callee2); }) ); return _foo.apply(this, arguments); }
function mark(genFn: () => void) { return _inheritsLoose(genFn, GeneratorFunctionPrototype); } function _inheritsLoose(subClass, superClass) { Object.setPrototypeOf(subClass, superClass); subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; return subClass; }
type GeneratorMethod = "next" | "return" | "throw"; class GeneratorFunctionPrototype { private _invoke: (method: GeneratorMethod, args) => { value: any, done: boolean }; // 注意这是原型方法哦 next(args) { return this._invoke("next", args); } return(args) { return this._invoke("return", args); } throw(args) { return this._invoke("throw", args); } }
async function a() { const res = await b(); } async function b() { await 1; await 'str'; return { data: 'lawler', msg: 'ok' }; }
function gen$(_context) { switch (_context.next) { case 0: _context.next = 7; return wait(10); case 7: // 传递 foo generator object 给 gen 的 context return _context.delegateYield(foo(), "t2", 8); case "end": return _context.stop(); } }
generator._invoke = function invoke(method, args) { context.method = method; // yield* genFn 时使用,循环返回 genFn 迭代的结果,直到 return while (true) { const delegate = context.delegate; if (delegate) { const delegateResult = maybeInvokeDelegate(delegate, context); if (delegateResult) { if (delegateResult === empty) continue; // 传出内部迭代结果 { value, done } return delegateResult; } } } if (method === "next") {} }