天之书-InjectFlags,谁懂我服

259 阅读3分钟

injectArgs这是angular种依赖注入代码摘录,看了半天,始终没有头绪,脑袋不够用了!感觉整个人都不好了!

export const enum InjectFlags {
    Default = 0 << 0, // 0b0000
    Host = 1 << 0, // 0b0001
    Self = 1 << 1, // 0b0010
    SkipSelf = 1 << 2, // 0b0100
    Optional = 1 << 3, // 0b1000 
}
Default0b0000 Host0b0001 Self0b0010 SkipSelf0b0100 Optional0b1000
Default0b0000 0b0000 0b0001 0b0010 0b0100 0b1000
Host0b0001 0b0001 0b0001 0b0011 0b0101 0b1001
Self0b0010 0b0010 0b0011 0b0010 0b0110 0b1010
SkipSelf0b0100 0b0100 0b0101 0b0110 0b0100 0b1100
Optional0b1000 0b1000 0b1001 0b1010 0b1100 0b1000

@Default() 0b0000 * @Host() 0b0001 * @Self() 0b0010 * @SkipSelf() 0b0100 * @Optional() 0b1000 = 0b1111 4个二进制第一位标示Host是否开启,二位表示Self是否开启,三位表示SkipSelf是否开启,4位表示Optional是否开启。

// 这样的代码跟天数有啥区别
export function injectArgs(
    types: (Type<any> | InjectionToken<any> | any[])[]
): any[] {
    const args: any[] = [];
    for (let i = 0; i < types.length; i++) {
        const arg = types[i];
        if (Array.isArray(arg)) {
            if (arg.length === 0) {
                throw new Error('Arguments array must have arguments.');
            }
            let type: Type<any> | undefined = undefined;
            let flags: InjectFlags = InjectFlags.Default;
            for (let j = 0; j < arg.length; j++) {
                const meta = arg[j];
                if (meta instanceof Optional || meta.ngMetadataName === 'Optional') {
                    flags |= InjectFlags.Optional;
                } else if (meta instanceof SkipSelf || meta.ngMetadataName === 'SkipSelf') {
                    flags |= InjectFlags.SkipSelf;
                } else if (meta instanceof Self || meta.ngMetadataName === 'Self') {
                    flags |= InjectFlags.Self;
                } else if (meta instanceof Inject) {
                    type = meta.token;
                } else {
                    type = meta;
                }
            }
            args.push(inject(type!, flags));
        } else {
            args.push(inject(arg));
        }
    }
    return args;
}
export const enum OptionFlags {
    Optional = 1 << 0, // 0b0001
    CheckSelf = 1 << 1, // 0b0010
    CheckParent = 1 << 2, // 0b0100
    Default = CheckSelf | CheckParent // 0b0110
}
Optional0b0001 CheckSelf0b0010 CheckParent0b0100 Default0b0110
Optional0b0001 0b0001 0b0000 0b0000 0b0000
CheckSelf0b0010 0b0000 0b0010 0b0000 0b0010
CheckParent0b0100 0b0000 0b0000 0b0100 0b0100
Default0b0110 0b0000 0b0010 0b0100 0b0110

@Optional & @Optional 不为0,其余均为0 @CheckSelf & @CheckSelf@CheckSelf & @Default 不为0,其余均为0 @CheckParent & @CheckParent@CheckParent & @Default 不为0,其余均为0 @Default & @Optional 为0,其余不为0

InjectFlags各个值&的话,只有自身与自身结果为正,其余均为0.

// 根据token解析出value
function resolveToken(
    token: any,
    record: Record | undefined,
    records: Map<any, Record>,
    parent: Injector,
    notFoundValue: any,
    flags: InjectFlags
): any {
    let value;
    // 没有SkipSelf
    if (record && !(flags & InjectFlags.SkipSelf)) {
        value = record.value;
        // circular
        if (value == CIRCULAR) {
            throw Error(NO_NEW_LINE + 'Circular dependency');
        } else if (value === EMPTY) { // empty
            record.value = CIRCULAR;
            let obj = undefined;
            let useNew = record.useNew;
            let fn = record.fn;
            let depRecords = record.deps;
            let deps = EMPTY;
            if (depRecords.length) {
                deps = [];
                for (let i = 0; i < depRecords.length; i++) {
                    const depRecord: DependencyRecord = depRecords[i];
                    const options = depRecord.options;
                    const childRecord =
                        // 如果是options = Default|CheckSelf
                        options & OptionFlags.CheckSelf ?
                            records.get(depRecord.token) : undefined;
                    deps.push(
                        // 递归
                        tryResolveToken(
                            depRecord.token,
                            childRecord,
                            records,
                            // childRecord && options != Default|CheckParent
                            !childRecord && !(options & OptionFlags.CheckParent) ? NULL_INJECTOR : parent,
                            // options == Default|Optional
                            options & OptionFlags.Optional ? null : Injector.THROW_IF_NOT_FOUND,
                            InjectFlags.Default
                        )
                    );
                }
            }
            record.value = value = useNew ? new (fn as any)(...deps) : fn.apply(obj, deps);
        }
    } else if (!(flags & InjectFlags.Self)) {
        // 获取上级
        value = parent.get(
            token,
            notFoundValue,
            InjectFlags.Default
        );
    }
    return value;
}
// 计算deps
function computeDeps(provider: StaticProvider): DependencyRecord[] {
    let deps: DependencyRecord[] = EMPTY;
    const providerDeps: any[] =
        (provider as ExistingProvider & StaticClassProvider & ConstructorProvider).deps;
    if (providerDeps && providerDeps.length) {
        deps = [];
        for (let i = 0; i < providerDeps.length; i++) {
            let options = OptionFlags.Default;
            let token = resolveForwardRef(providerDeps[i]);
            if (token instanceof Array) {
                for (let j = 0, annotations = token; j < annotations.length; j++) {
                    const annotation = annotations[j];
                    if (annotation instanceof Optional || annotation == Optional) {
                        options = options | OptionFlags.Optional;
                    } else if (annotation instanceof SkipSelf || annotation == SkipSelf) {
                        // 按位取反运算符 (~)
                        options = options & ~OptionFlags.CheckSelf;
                    } else if (annotation instanceof Self || annotation == Self) {
                        // 按位取反运算符 (~)
                        options = options & ~OptionFlags.CheckParent;
                    } else if (annotation instanceof Inject) {
                        token = (annotation as Inject).token;
                    } else {
                        token = resolveForwardRef(annotation);
                    }
                }
            }
            deps.push({ token, options });
        }
    } else if ((provider as ExistingProvider).useExisting) {
        const token = resolveForwardRef((provider as ExistingProvider).useExisting);
        deps = [{ token, options: OptionFlags.Default }];
    } else if (!providerDeps && !(USE_VALUE in provider)) {
        throw staticError('\'deps\' required', provider);
    }
    return deps;
}

我给你跪了!都是什么鬼!