Skip to content

JavaScript 用法

InferDI 使用 TypeScript 编写,但 JavaScript 项目通过 package exports 映射来使用已构建的 npm 包。

示例展示内容
node-esm.mjs在 Node 中使用 ESM 导入,配合 // @ts-check 和 JSDoc 构造函数类型
node-commonjs.cjs在 Node 中通过 package exports 映射使用 CommonJS require()
browser-vite.js面向浏览器的 ESM,适用于 Vite 或其他打包工具

Node ESM

js
// @ts-check

import { Container } from '@inferdi/inferdi'

class Logger {
  /**
   * @param {string} message
   */
  log(message) {
    console.log(`[LOG] ${message}`)
  }
}

class UserService {
  /**
   * @param {Logger} logger
   * @param {string} apiToken
   */
  constructor(logger, apiToken) {
    this.logger = logger
    this.apiToken = apiToken
  }

  /**
   * @param {string} id
   */
  find(id) {
    this.logger.log(`Finding user ${id} with token ${this.apiToken}`)
    return { id, name: 'Alice' }
  }
}

const container = new Container()
  .registerValue('token', 'secret-123')
  .registerClass('logger', Logger, [])
  .registerClass('userService', UserService, ['logger', 'token'])

/*
 * Uncomment in an editor with JavaScript type checking enabled:
 * new Container()
 *   .registerValue('token', 'secret-123')
 *   .registerClass('logger', Logger, [])
 *   .registerClass('userService', UserService, ['token', 'logger'])
 */

console.log(container.get('userService').find('42'))

/*
 * If your runtime/toolchain supports Explicit Resource Management syntax,
 * Container also supports: await using container = new Container()
 */
await container.dispose()

仓库文件:examples/javascript/node-esm.mjs

Node CommonJS

js
// @ts-check

const { Container } = require('@inferdi/inferdi')

class Logger {
  /**
   * @param {string} message
   */
  log(message) {
    console.log(`[LOG] ${message}`)
  }
}

class UserService {
  /**
   * @param {Logger} logger
   * @param {string} apiToken
   */
  constructor(logger, apiToken) {
    this.logger = logger
    this.apiToken = apiToken
  }

  /**
   * @param {string} id
   */
  find(id) {
    this.logger.log(`Finding user ${id} with token ${this.apiToken}`)
    return { id, name: 'Alice' }
  }
}

async function main() {
  const container = new Container()
    .registerValue('token', 'secret-123')
    .registerClass('logger', Logger, [])
    .registerClass('userService', UserService, ['logger', 'token'])

  /*
   * Uncomment in an editor with JavaScript type checking enabled:
   * new Container()
   *   .registerValue('token', 'secret-123')
   *   .registerClass('logger', Logger, [])
   *   .registerClass('userService', UserService, ['token', 'logger'])
   */

  console.log(container.get('userService').find('42'))

  /*
   * If your runtime/toolchain supports Explicit Resource Management syntax,
   * Container also supports: await using container = new Container()
   */
  await container.dispose()
}

main().catch((error) => {
  console.error(error)
  throw error
})

仓库文件:examples/javascript/node-commonjs.cjs

在浏览器中使用 Vite

js
// @ts-check

import { Container } from '@inferdi/inferdi'

class PageContext {
  constructor() {
    this.pageName = ''
  }
}

class ApiClient {
  async listProjects() {
    return [{ id: 'project_1', name: 'Docs' }]
  }
}

class ProjectsViewModel {
  /**
   * @param {PageContext} page
   * @param {ApiClient} api
   */
  constructor(page, api) {
    this.page = page
    this.api = api
  }

  async load() {
    return {
      page: this.page.pageName,
      projects: await this.api.listProjects()
    }
  }
}

const root = new Container()
  .registerClass('page', PageContext, [], 'scoped')
  .registerClass('api', ApiClient, [])
  .registerClass('projectsVm', ProjectsViewModel, ['page', 'api'], 'scoped')

/*
 * Uncomment in an editor with JavaScript type checking enabled:
 * new Container()
 *   .registerClass('page', PageContext, [], 'scoped')
 *   .registerClass('api', ApiClient, [])
 *   .registerClass('projectsVm', ProjectsViewModel, ['api', 'page'], 'scoped')
 */

export function createProjectsPageScope() {
  const scope = root.createScope()

  try {
    scope.get('page').pageName = 'projects'
    return scope
  } catch (error) {
    scope.dispose().catch(console.error)
    throw error
  }
}

/**
 * @param {HTMLElement} element
 */
export async function renderProjectsList(element) {
  const scope = createProjectsPageScope()

  try {
    const vm = scope.get('projectsVm')
    const data = await vm.load()

    element.textContent = `${data.page}: ${data.projects.map((project) => project.name).join(', ')}`
  } finally {
    await scope.dispose()
  }
}

仓库文件:examples/javascript/browser-vite.js