@ethanresnick/bottlejs

中文文档
2.0.4发布于 2022/04/06MITTypeScriptESM + CJS零依赖近 30 天下载 1.1万

强大的依赖性注射微型容器

中文使用文档
文档目录15 节
  1. 导言
  2. 浏览器支持
  3. 安装
  4. 简单示例
  5. 注入依赖
  6. 服务厂
  7. 服务提供者
  8. 装饰者
  9. 中间软件
  10. 薄膜瓶
  11. 封闭的容器被隔离
  12. API 密码
  13. 瓶装
  14. 瓶.原型
  15. 类型脚本

BottleJS

瓶子JS

Build Status npm version dependencies Status Known Vulnerabilities

NPM

强大的依赖性注射微型容器

导言

BottleJS是一个微小而强大的依赖性注射容器. 它的特点是懒惰地装入,中器件钩子,装饰器和由受此启发的干净的阿皮 AngularJS 模块 API 和简单的 PHP 库 小猪你会喜欢瓶子JS的,如果你喜欢:

  • 建起一个堆栈,而不是一个厨房-水槽框架.
  • 无关联物体和依赖性注射.
  • aPI是有意义的.
  • 懒惰地装入物体.
  • 尝试很酷的东西 : smile :

浏览器支持

BottleJS支持IE9+和其他ECMAScript 5兼容浏览器.

安装

BottleJS可用于浏览器或节点应用. 可通过弓形或npm安装:

$ bower install bottlejs
$ npm install bottlejs

Cdnjs上也有瓶子JS:

<script src="https://cdnjs.cloudflare.com/ajax/libs/bottlejs/1.7.1/bottle.min.js"></script>

简单示例

最简单的食谱开始于 Bottle#service。说你有一个服务对象的构造器:

var Beer = function() { /* A beer service, :yum: */ };

您可以用 Bottle#service数字 :

var bottle = new Bottle();
bottle.service('Beer', Beer);

稍后,当你需要构建的服务, 你只是访问 Beer 像这样的属性 :

bottle.container.Beer;

幕后发生了很多事:

  1. 瓶子在您注册啤酒服务时创建了一个包含工厂功能的供应商.
  2. 当 bottle.container.Beer bottle查了一下供货商 并处决了工厂 建造和归还啤酒服务.
  3. 供应商和工厂被删除 bottle.container.Beer 财产被设定为啤酒服务案例。 访问 bottle.container.Beer 将来会变成一个简单的财产查询.

注入依赖

以上例子很简单。 但是,如果啤酒服务 有依赖性呢? 例如:

var Barley = function() {};
var Hops = function() {};
var Water = function() {};
var Beer = function(barley, hops, water) { /* A beer service, :yum: */ };

您可以向您注册服务 Bottle#service 并包含此类依赖性:

var bottle = new Bottle();
bottle.service('Barley', Barley);
bottle.service('Hops', Hops);
bottle.service('Water', Water);
bottle.service('Beer', Beer, 'Barley', 'Hops', 'Water');

现在,当你进入 bottle.container.Beer瓶子会轻而易举地装入所有依附物 并注入你的啤酒服务 然后再退货.

服务厂

如果您在生成服务时需要更复杂的逻辑,您可以注册工厂。 工厂功能接收容器作为论据,并应当返回您构建的服务:

var bottle = new Bottle();
bottle.service('Barley', Barley);
bottle.service('Hops', Hops);
bottle.service('Water', Water);
bottle.factory('Beer', function(container) {
    var barley = container.Barley;
    var hops = container.Hops;
    var water = container.Water;

    barley.halved();
    hops.doubled();
    water.spring();
    return new Beer(barley, hops, water);
});

服务提供者

这是瓶子库的肉. 上述方法 Bottle#service 财务报告和审定财务报表 Bottle#factory 仅是提供者函数的快手。 通常您可以通过上面的简单函数,但是如果您真的需要在不同环境中对您的服务进行更颗粒化的控制,请将其注册为提供者. 为了使用它,通过一个建筑师 供供应商暴露 $get 函数。 这个 $get 函数用作构建您的服务的工厂.

var bottle = new Bottle();
bottle.service('Barley', Barley);
bottle.service('Hops', Hops);
bottle.service('Water', Water);
bottle.provider('Beer', function() {
    // This environment may not support water.
    // We should polyfill it.
    if (waterNotSupported) {
        Beer.polyfillWater();
    }

    // this is the service factory.
    this.$get = function(container) {
        var barley = container.Barley;
        var hops = container.Hops;
        var water = container.Water;

        barley.halved();
        hops.doubled();
        water.spring();
        return new Beer(barley, hops, water);
    };
});

装饰者

瓶子支持用 Bottle#decorator 方法。 瓶装装饰器只是简单的功能,在服务创建后在提供者阶段拦截服务,但在首次访问之前. 该函数应当返回服务,或者另一个要用作服务的对象.

var bottle = new Bottle();
bottle.service('Beer', Beer);
bottle.service('Wine', Wine);
bottle.decorator(function(service) {
    // this decorator will be run for both Beer and Wine services.
    service.stayCold();
    return service;
});

bottle.decorator('Wine', function(wine) {
    // this decorator will only affect the Wine service.
    wine.unCork();
    return wine;
});

中间软件

瓶子中件与装饰相类似,但每次从容器访问服务时都会被执行. 他们通过 服务案例和a next 函数 :

var bottle = new Bottle();
bottle.service('Beer', Beer);
bottle.middleware(function(service, next) {
    // this middleware will be executed for all services
    console.log('A service was accessed!');
    next();
});

bottle.middleware('Beer', function(beer, next) {
    // this middleware will only affect the Beer service.
    console.log('Beer?  Nice.  Tip your bartender...');
    next();
});

中间软件可以将一个错误对象传递到 next 函数,瓶会丢出错误:

var bottle = new Bottle();
bottle.service('Beer', Beer);
bottle.middleware('Beer', function(beer, next) {
    if (beer.hasGoneBad()) {
        return next(new Error('The Beer has gone bad!'));
    }
    next();
});

// results in Uncaught Error: The Beer has gone bad!(…)

薄膜瓶

如果在服务名中使用了点标记,瓶会生成嵌入式容器. 将根据给定的名称为您创建一个孤立的子容器:

var bottle = new Bottle();
var IPA = function() {};
bottle.service('Beer.IPA', IPA);
bottle.container.Beer; // this is a new Bottle.container object
bottle.container.Beer.IPA; // the service
bottle.factory('Beer.DoubleIPA', function (container) {
    var IPA = container.IPA; // note the container in here is the nearest parent.
})

封闭的容器被隔离

嵌入式容器旨在提供不同包件之间的隔离. 这意味着在写作工厂时,您无法访问来自不同家长的嵌入式容器.

var bottle = new Bottle();
var IPA = function() {};
var Wort = function() {};
bottle.service('Ingredients.Wort', Wort);
bottle.factory('Beer.IPA', function(container) {
    // container is `Beer`, not the root, so:
    container.Wort; // undefined
    container.Ingredients.Wort; // undefined
});

API 密码

瓶装

弹出( 名称)

曾取一瓶来. 如果一个名字被通过,瓶子会返回同样的例子. 调用瓶子构造器作为函数将调用并返回 Bottle.pop这样 Bottle.pop('Soda') === Bottle('Soda')

参数类型细节
名称
(可选)
字符串取出瓶名来. 如果通过,瓶子将在内部存储实例,如果 Bottle.pop 后被取同名.

清除( 名称)

从瓶子的内部仓库中删除命名实例,如果存在的话。 随即发出的呼吁 Bottle.pop(name) 将返回一个新的实例。 如果没有给出姓名,所有已命名的实例都会被清除.

一般来说,只有在您打算与新的提供者,装饰者等重置瓶子时,例如测试设置时,才应当调用此功能.

参数类型细节
名称
(可选)
字符串取出瓶名来. 如果通过, 如果使用 Bottle.pop。如果不通过,所有已命名的内部实例都将被清除.

列表(容器)

原型. list( )

原型. container.$list( )

用于列出集装箱上所有已登记常数、值和服务的名称。 必须将容器传递到全局静态版本 Bottle.list(bottle.container)。实例和集装箱版本返回在其中注册的服务.

返回一系列字符串.

参数类型细节
集装箱
(可选)
对象A 类 bottle.container。仅在使用全球静态时才需要 Bottle.list 方法。 原型版本使用那个实例的容器,而容器版本则使用自己.

配置

全局配置对象 .

财产类型默认细节
严格布尔false启用严格模式 。 目前仅核实自动注入的依赖性不是未定义的.

瓶.原型

装饰器

由瓶子实例注册的装饰器收藏. 见 decorator(name, func) 下级

中间软件

瓶子实例注册的中相器件集. 见 middleware(name, func) 见下文.

筑巢

当点名用于定义服务时,由母瓶实例注册的嵌入瓶集合. 参见以上文献"巢"部分.

提供者映射

注册提供者名集. 瓶子在内部用它来确定 提供商是否已经即时化了它的例子。 见 provider(name, Provider) 见下文.

推迟

此瓶子实例已注册的一系列延期函数 。 见 defer(func) 见下文.

常数( 名称, 值)

曾经只在容器上添加一个读取值.

参数类型细节
名称字符串常相之名为相. 必须是每个瓶子的例子独有的.
价值混合将定义为可假设但不可写入的值 .

装饰器( 名称, func)

标记器(名称, func)

用于注册一个装饰器功能, 由提供者在创建时用于修改您的服务 . bottle.container.$decorator 是一种异名 bottle.decorator;这只允许您在嵌入的瓶子上添加一个装饰器.

参数类型细节
名称
(可选)
字符串此装饰器将影响服务的名称 。 如果没通过,所有服务都会通过.
乐趣c函数将接受服务作为第一个参数的函数 。 返回服务,或用作服务的新对象.

推迟( 已关闭)

注册待执行的函数 Bottle#resolve 名为.

参数类型细节
乐趣c函数函数待后取名. 将传递给 Bottle#resolve。 。 。 .

文摘(服务)

立即立即提供各种服务并返回其实例 按实例的顺序排列.

参数类型细节
服务阵列各种服务应当立即进行.

工厂(名称、工厂)

曾注册服务厂

参数类型细节
名称字符串服务名. 必须是每个瓶子的例子独有的.
工厂函数一个应该返回服务对象的函数。 只有一次被调用;服务会是一个单通. 在创建服务时,通过一个容器实例允许依赖性注射.

实例事实( 名称、 工厂)

曾经注册一个服务实例工厂,当被调用时会返回一个实例.

参数类型细节
名称字符串服务名. 必须是每个瓶子的例子独有的.
工厂函数一个函数,该函数应返回一个完全配置的服务对象。 当创建新实例时, 此工厂函数将执行 。 过了一个集装箱的例子.
var bottle = new Bottle();
var Hefeweizen = function(container) { return { abv: Math.random() * (6 - 4) + 4 }};
bottle.instanceFactory('Beer.Hefeweizen', Hefeweizen);

var hefeFactory = bottle.container.Beer.Hefeweizen; // This is an instance factory with a single `instance` method

var beer1 = hefeFactory.instance(); // Calls factory function to create a new instance
var beer2 = hefeFactory.instance(); // Calls factory function to create a second new instance

beer1 !== beer2 // true

这种模式对于基于请求的上下文对象存储状态或数据库连接等东西特别有用. 见Google Guice的文档 输入器 需要更多的实例.

中件( 名称, func)

用于注册中间软件函数 。 每次访问服务时都会执行此功能.

参数类型细节
名称
(可选)
字符串此中件将调用的服务的名称 。 如果没通过,所有服务都会通过.
乐趣c函数接受服务作为第一个参数的函数,以及 a next 函数作为第二个参数。 应执行 next() 允许堆栈中的其他中间软件执行。 瓶子会扔任何传递给 next 函数,即. next(new Error('error msg'))。 。 。 .

提供者( 名称, 提供者)

用于注册服务供应商

参数类型细节
名称字符串服务名. 必须是每个瓶子的例子独有的.
提供者函数一个构造器函数,将以单子即时化. 显示一个名为 $get 将被用作工厂 以即时服务.

重置提供者( 名)

参数类型细节
名称
(可选)
阵列包含要重置的提供者名称的字符串 .

用于重置提供者,供下个参考,以重新证实提供者。 若为 names parm 已通过,将仅重置命名的提供者 .

注册( Obj)

注册人(Obj)

用于根据Obj的属性登记服务、工厂、提供者或价值. bottle.container.$register 是一种异名 bottle.register;这使得工厂和提供商可以在容器上注册多种服务而不需要使用瓶子实例本身.

若为 Bottle.config.strict 设置为 true,如果注入的依赖性是 undefined。 。 。 .

参数类型细节
欧比对象|函数具有若干属性之一的物体或构造器:
  • Obj.$名称 —— 说 所需经费 ——用于登记对象的名称
  • Obj.$类型 —— 说 选项 ——用于登记对象的方法. 默认为 'service' 在这种情况下,Obj将被视为建筑师。 有效类型为: 'service', (中文(简体) ), 'factory', (中文(简体) ), 'provider', (中文(简体) ), 'value'
  • Obj. $喷出 —— 说 选项 如果 Obj.$type 实值 'service',这个属性可以是字符串名称或一系列依赖性名称来注入到构建器中.
    举个例子. Obj.$inject = ['dep1', 'dep2'];
  • 价值 —— 说 选项 - Obj通常在集装箱上登记。 然而,如果包括了这种地产,则其价值将在容器上而不是物体本身上注册. 用于在瓶装箱上登记物体,而不修改带有瓶装特定钥匙的物体.

解析( 数据)

执行任何已注册的延期函数 Bottle#defer。 。 。 .

参数类型细节
数据
(可选)
混合要传递到每个被推迟的函数作为第一个参数的值 .

服务( 名称、 构造器 [, 依赖性 [,...]])

曾注册服务建筑师. 若为 Bottle.config.strict 设置为 true,如果注入的依赖性是 undefined。 。 。 .

参数类型细节
名称字符串服务名. 必须是每个瓶子的例子独有的.
构造器函数一个构造器函数,将以单子即时化.
依赖性
(可选)
字符串一个可选的名称,用于将依赖性传递给构建者 。 将每个名称转给构造者 Bottle#service 按排列顺序排列.

服务事实( 名称, 工厂服务 [, 依赖性 [,...]])

曾注册服务工厂功能. 完全一样 factory 除了工厂的参数会被注入而不是接收 container。这在执行模块模式或为您的高阶函数添加依赖性时是有用的.

function packageKeg(Barrel, Beer, Love) {
    Barrel.add(Beer, Love);
    return {
        tap : function() {
            return Barrel.dispense();
        }
    };
}
bottle.serviceFactory('Keg', packageKeg, 'Barrel', 'Beer', 'Love');

若为 Bottle.config.strict 设置为 true,如果注入的依赖性是 undefined。 。 。 .

参数类型细节
名称字符串服务名. 必须是每个瓶子的例子独有的.
服务事实函数用于创建服务对象/值的函数.
依赖性
(可选)
字符串将依赖性传递到服务函数的可选名称 。 对每个名称的依赖将传递给服务职能 Bottle#serviceFactory 按排列顺序排列.

值( 名称, val)

曾为容器添加任意值.

参数类型细节
名称字符串值所取之名. 必须是每个瓶子的例子独有的.
val 时混合将定义为可假设但不可写入的值 .

类型脚本

TypeScript 声明文件被捆绑在这个包中. 要让 TypeScript 自动解析, 您需要设置 moduleResolution 改为 node 在你身边 tsconfig.json。 。 。 .

版本与发布记录

@ethanresnick/bottlejs 共发布 4 个版本,首次发布于 2022/04/06;过去 12 个月发布了 0 个版本。

版本发布日期距今
2.0.4latest2022/04/064 年前
2.0.32022/04/064 年前
2.0.22022/04/064 年前
2.0.12022/04/064 年前

关于 @ethanresnick/bottlejs 的常见问题

@ethanresnick/bottlejs 是什么?

强大的依赖性注射微型容器

如何安装 @ethanresnick/bottlejs?

在项目目录运行 npm install @ethanresnick/bottlejs,或使用 pnpm add / yarn add / bun add。

@ethanresnick/bottlejs 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@ethanresnick/bottlejs 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@ethanresnick/bottlejs 可以商用吗?

@ethanresnick/bottlejs 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@ethanresnick/bottlejs 的下载量有多少?

根据 npm 官方下载统计,@ethanresnick/bottlejs 在 2026/10/14 – 2026/11/12 这 30 天内被下载 11,062 次,日均约 369 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@ethanresnick/bottlejs 还在维护吗?

最新版本 2.0.4 发布于 2022/04/06(4 年前);至今共发布 4 个版本,其中过去 12 个月发布了 0 个;首次发布于 2022/04/06。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。