0

我正在尝试通过创建一个 web3 服务来将 Web3 与 Angular 4 正确集成,该服务需要等待窗口加载,然后才能检查 window.web3 是否被注入。我们应该只有在完成后才能查询此服务。以下是 Metamask 文档摘录中的相关代码:

window.addEventListener('load', function() {

  // Checking if Web3 has been injected by the browser (Mist/MetaMask)
  if (typeof web3 !== 'undefined') {
    // Use Mist/MetaMask's provider
    window.web3 = new Web3(web3.currentProvider);
  } else {
    console.log('No web3? You should consider trying MetaMask!')
    // fallback - use your fallback strategy (local node / hosted node + in-dapp id mgmt / fail)
    window.web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
  }

  // Now you can start your app & access web3 freely:
  startApp()

})

我发现这个其他答案似乎可以满足我的要求,但是将 Promise 转换为 Observable。

我如何初始化一个围绕这个 web3 对象的 Angular4 服务,以使对 web3 成员的任何请求都将等待它被初始化?

现在我使用的代码使用间隔,但我不喜欢它,因为它感觉很乱。

4

1 回答 1

0

在你引导你的主模块之后,你会得到一个主模块的实例,其中包含 Angular 将用来实例化你的提供者的注入器的实例。因此,您可以获取该实例并将其存储在某处,然后使用它来实例化提供程序。

假设您想将应用程序的注入器存储在 app-injector.ts 中,所以它看起来像,

//app-injector.ts

import { Injector } from '@angular/core';

let appInjectorRef: Injector;

export const appInjector = (injector?: Injector): Injector => {
    if (!injector) {
        return appInjectorRef;
    }

    appInjectorRef = injector;

    return appInjectorRef;
};

在你的主模块的引导程序中可能看起来像,

platformBrowserDynamic()
  .bootstrapModule(TopLevelModule)
  .then((appRef: any) => {
    appInjector(appRef['injector']); // grab the injector instance and store.
  })
  .catch((err) => console.error(err));

接下来,例如在您的 AppComponent 中,您可以这样做,

import {appInjector} from './app-injector';
export class AppComponent implements OnInit {
     private service: ServiceThatUsesWeb3;

     ngOnInit(): void {
        //.. do web3 instantiation stuffs.
        setTimeout(() => {
          service = appInjector().get(ServiceThatUsesWeb3);
          // use the service.
        });
     }
}

请注意 setTimeout() 很重要,否则 appInjector() 将返回未定义。

于 2017-10-22T16:00:27.730 回答