interface INewNumberextends number {} // 'number' only refers to a type, but is being used as a value here.
interface INewNumberextendsNumber {} // 这样写是可以的,但是不要忘记 1 instanceof Number === false
元组 不能使用 interface 声明元组
1 2 3 4 5 6 7 8 9 10 11
type Tuples = [number, number];
interface ITuples { 0: number; 1: number; }
[1, 2, 3] asTuples; // Conversion of type '[number, number, number]' to type 'Tuples' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first. Types of property 'length' are incompatible.
[1, 2, 3] asITuples;
不相关的合集 只有 type 可以做不相关合集
1
type SomeAnimal = { type: Dog } | { type: Cat };
且不能对 不相关集合不能使用 extends 关键字
1 2
interface ISomeAnimalextendsSomeAnimal {} // An interface can only extend an object type or intersection of object types with statically known members
每个作用域只能声明一次类型
1 2 3
type Once = { a: string }; type Once = { b: string }; // Duplicate identifier 'Once'
协程是一种比线程更加轻量级的存在。可以把协程看成是跑在线程上的任务,一个线程上可以存在多个协程,但是在线程上同时只能执行一个协程,比如当前执行的是 A 协程,要启动 B 协程,那么 A 协程就需要将主线程的控制权交给 B 协程,这就体现在 A 协程暂停执行,B 协程恢复执行;同样,也可以从 B 协程中启动 A 协程。通常,如果从 A 协程启动 B 协程,我们就把 A 协程称为 B 协程的父协程。
协程有点像函数,又有点像线程。它的运行流程大致如下。
第一步,协程 A 开始执行。
第二步,协程 A 执行到一半,进入暂停,执行权转移到协程 B。
第三步,(一段时间后)协程 B 交还执行权。
第四步,协程 A 恢复执行。
上面流程的协程 A,就是异步任务,因为它分成两段(或多段)执行。
举例来说,读取文件的协程写法如下。
1 2 3 4 5
functionasnycJob() { // ...其他代码 var f = yieldreadFile(fileA); // ...其他代码 }
functionco(gen) { if (typeof gen === 'function') gen = gen.apply(ctx, args); onFulfilled();
functiononFulfilled(res) { var ret; try { ret = gen.next(res); } catch (e) { returnreject(e); } next(ret); } functionnext(ret) { if (ret.done) returnresolve(ret.value); var value = toPromise.call(ctx, ret.value); if (value && isPromise(value)) return value.then(onFulfilled, onRejected); returnonRejected( newTypeError( 'You may only yield a function, promise, generator, array, or object, ' + 'but the following object was passed: "' + String(ret.value) + '"' ) ); } }
这儿,在给 co 传入一个generator函数后,co 会将其自动启动。然后调用onFulfilled函数。在onFulfilled函数内部,首先则是获取 next 的返回值。交由next函数处理。 而next函数则首先判断是否完成,如果这个 generator 函数完成了,返回最终的值。否则则将yield后的值,转换为Promise。最后,通过Promise的 then,并将onFulfilled函数作为参数传入。
1 2 3
if (value && isPromise(value)) { return value.then(onFulfilled, onRejected); }
而在generator中,yield句本身没有返回值,或者说总是返回undefined。而 next 方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。同时通过onFulfilled函数,则可以实现自动调用。这也就能解释为什么 co 基于Promise。且能自动执行了。
functionco(gen) { var ctx = this; var args = slice.call(arguments, 1);
// we wrap everything in a promise to avoid promise chaining, // 把传进来的所有东西都转为 promise // which leads to memory leak errors. // see https://github.com/tj/co/issues/180 returnnewPromise(function (resolve, reject) { // 执行 gen 函数 if (typeof gen === 'function') gen = gen.apply(ctx, args); // gen函数返回的 gen 指针不存在或 gen.next 不是函数(意味着 gen 不是 Generator函数) 则返回空值 if (!gen || typeof gen.next !== 'function') returnresolve(gen);
onFulfilled();
/** * @param {Mixed} res * @return {Promise} * @apiprivate * 把每次 yield 之后的异步函数的返回结果当做参数传回 generator 函数 * eg. let a = yeild b * 此时经过 onFulfilled 函数的处理 a === b() */ functiononFulfilled(res) { var ret; try { /** * gen.next(res),则是向generator函数传参数,作为yield的返回值 * ret 是 gen.next() 返回的对象 * --- * yield 语句本身没有返回值,或者说总是返回undefined。 * next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。 */ ret = gen.next(res); } catch (e) { returnreject(e); } // 每完成一次 yield,把返回的对象交给 next() 处理 next(ret); }
/** * Get the next value in the generator, * return a promise. * 把 gen.next() 返回对象中的 value 变为 promise * * @param {Object} ret * @return {Promise} * @apiprivate */
functionnext(ret) { /** * 如果这个generator函数完成了,返回最终的值 * 假设我们写的 generator函数没有 return someValue, 在所有yield完成后,调用next()会返回{valu: undefined, done: true} * 所以需要手动return一个值。这样最后的value才不是undefined */ if (ret.done) returnresolve(ret.value); // 这个generator函数还没结束, 就统一交给 toPromise() 处理 var value = toPromise.call(ctx, ret.value); // 这里value.then(onFulfilled, onRejected),实际上已经调用并传入了 onFulfilled, onRejected 两个参数。 // 把 onFulfilled 函数传入 value if (value && isPromise(value)) return value.then(onFulfilled, onRejected); returnonRejected( newTypeError( 'You may only yield a function, promise, generator, array, or object, ' + 'but the following object was passed: "' + String(ret.value) + '"' ) ); } }); }