1. 程式人生 > 實用技巧 >angular裡forwardRef的原理

angular裡forwardRef的原理

一段會報錯的angular程式碼

@Injectable()
class Socket {
  constructor(private buffer: Buffer) { }
}

console.log(Buffer); // undefined

@Injectable()
class Buffer {
  constructor(@Inject(BUFFER_SIZE) private size: Number) { }
}

console.log(Buffer); // [Function: Buffer]

翻譯一下

    var providerList = new Map();
    function Injectable(cls, deps) {
      providerList.set(cls, {
        deps: deps,
        instance: null
      });
    }

    function inject(cls) {
      var instanceObj = providerList.get(cls);
      if (instanceObj === undefined) {
        return null;
      } else if (instanceObj.instance === null) {
        var deps = instanceObj.deps.map(dep => inject(dep));
        var instance = cls.apply({}, deps);
        instanceObj.instance = instance;
        return instance;
      } else {
        return instanceObj.instance;
      }
    }

    var Socket = (function() {
      function Socket(buffer) {
        this.buffer = buffer;
        return this;
      }
      Injectable(Socket, [Buffer]);
      return Socket;
    }());

    var Buffer = (function () {
      function Buffer() {
        this.sayHello = function() {
          console.log('hello, i am Buffer.');
        }
        return this;
      }
      Injectable(Buffer, []);
      return Buffer;
    }());

    var socket = inject(Socket);
    socket.buffer.sayHello();
Socket被注入的時候,他的依賴Buffer還是undefined狀態,最後取出來的就是undefined.
看看angular怎麼用forwardRef解決這個問題的
@Injectable()
class Socket {
  constructor(@Inject(forwardRef(() => Buffer) private buffer) { }
}

@Injectable()
class Buffer {
  constructor() { }
}

翻譯一下

    function forwardRef(forwardRefFn) {
      forwardRefFn.__forward_ref__ 
= forwardRef; return forwardRefFn; } function resolveForwardRef(type) { if (typeof type === 'function' && type.hasOwnProperty('__forward_ref__') && type.__forward_ref__ === forwardRef) { return type(); } else { return type; } }
var providerList = new Map(); function Injectable(cls, deps) { providerList.set(cls, { deps: deps, instance: null }); } function inject(cls) { cls = resolveForwardRef(cls); var instanceObj = providerList.get(cls); if (instanceObj === undefined) { return null; } else if (instanceObj.instance === null) { var deps = instanceObj.deps.map(dep => inject(dep)); var instance = cls.apply({}, deps); instanceObj.instance = instance; return instance; } else { return instanceObj.instance; } } var Socket = (function() { function Socket(buffer) { this.buffer = buffer; return this; } Injectable(Socket, [forwardRef(() => Buffer)]); return Socket; }()); var Buffer = (function () { function Buffer() { this.sayHello = function() { console.log('hello, i am Buffer.'); } return this; } Injectable(Buffer, []); return Buffer; }()); var socket = inject(Socket); socket.buffer.sayHello();

原理就是依賴不再是類了,而是一個返回類的函式,這樣在inject的時候避免注入undefined。