1

Provider

前言

Zeta.js 是一款为node打造的轻量级后端框架,引入了许多angular的概念,可以让你以一种不同于express的更有层次的方式编写后端代码。这里是Zeta的中文文档。

Source On GitHub

Website For Zeta

概览

正如它的名字,Provider抽象出应对不同请求时的处理里相同部分的工作并为它提供服务。一个Provider本质上就是一个对象,包含属性和方法,从属于一个module。Provider是一个逻辑上的概念,可以通过module间的依赖注入继承。

开始

定义Provider

Provider是被module注册的,就像下面给出的代码一样。

jsdemoProvider.provider('$sayhi',{
    content:"hi,world",
    say:function(){ return this.content;}
});
//demoProvider is a module

现在,你得到了一个名叫$sayhi的provider,字母“$” 并非必要的,但我们推荐你把它放在你所选定的Provider名字的开头以将Provider与普通的变量区分开来。

Provider可以被定义成你想要的任何样子,只要它是个对象,当然也就包括函数了。请看下面的例子。

jsdemoProvider.provider('$plus',function(a,b){
    return a+b;
});

使用Provider

Provider存在的意义就是抽象出对于一类相似请求所要进行的操作里的相似部分以供代码复用,所以它显然应该被请求处理函数所使用。 下面给出一个实例。

jsdemo.provider('$sayhi',{
    content:"hi,world",
});
demo.get('/',function($scope,$sayhi){
    $scope.send($sayhi.content).end();
});

在上面的例子中我们使用Provider $sayhi来向客户端发送一个字符串“hi,world”,当对于路径'/'的请求到达的时候。应该注意到如果你想使用Provider,应该把它对应的注册时的名字加到请求处理函数的参数列表里。

取出Provider

如果你已经定义了一个Provider,你可以通过下面的方式在其他地方取到这个对象。

jsvar pro=demo.provider('$sayhi');
console.log(pro.content);
//get 'hi,world' when $sayhi defined
//else undefined got

为什么使用Provider

看到,你们或许有一个问题,为什么我们要有Provider这个概念。以上面的例子为例,为什么不直接返回一个字符串呢?考虑下面的场景。

jsdemo.get('/abc',function($scope,$sayhi){
    $scope.send($sayhi.content+'abc').end();
});
demo.get('/efg',function($scope,$sayhi){
    $scope.send($sayhi.content+'efg').end();
});
....

对于许多路径你可能都要做一部分相同的事情,但是现在你想把hi换成hello,使用Provider的情况下,只用修改Provider的定义。

jsdemo.provider('$sayhi',{
    content:"hello,world",
});

否则就只能呵呵了。当然这个例子举的并不是很好,但可以说明Provider设计的目的,在接下来的内容里会更详细地讲在何时使用Provider。

一个简单的例子

接下来我们会给出一个稍微复杂的例子,以让你对于Provider有一个全局上的把握,里面如果有新的概念可以直接忽略。

js//main.js file
var zeta=require('zeta');
var demo=zeta.module('demo',['demoProvider']);
demo.load();
demo.get('/',function($scope,$home){
    $scope.render($home(),{
        title:'Home'
    });
});
js//Provider.js
var zeta=require('zeta');
var demoProvider=zeta.module('demoProvider',[]);
demoProvider.provider('$home',function(){
    return '/public/home.html';
});

正如你所看到的,Provider可以通过module间的依赖注入被继承,但不要忘记load过程。

Provider进阶

Provider使用Provider

在我们的设计中,当你定义当前的Provider去引用其他Provider是十分简单地。

jsdemo.provider('$hi',{
    content:'hi,world'
});
demo.provider('$say',function($hi){
    return $hi.content;
});

Provider使用工厂

对于这一部分内容,我们推荐你看完下一章节再回过头来阅读。

jsdemo.factory('$count',function(){
      return function(a,b){return a+b;};
});
demo.provider('$wel',function($count){
      return $count(1,2);
});

Provider使用工厂的方式和前面使用Provider基本一致。

何时使用Provider

我们引入Provider这个概念是为了代码复用,所以它应该被用于解决低层次的通用性的工作,比如说包装关于数据库的操作。

jsvar $db={};
$db.url='http://localhost;5000';
$db.connect=function(){...};
$db.save=function(obj){...};
$db.del=function(obj){...};
$db.find=function(obj){...};
demo.provider('$db',$db);

这是一个合理的设计,但是一些通用性不强仅仅在极少量请求处理函数里会用到的不一致的操作就不适合写成Provider。另外一个正面的例子是你可以把对于同引擎的文件渲染包装成一个Provider--$render。除此之外,对于每一个独立的请求都需要一个新的对象为它提供服务的场景,我们推荐你使用工厂而非Provider。

注意

  • Provider可以通过重定义覆盖
jsdemo.provider('$say',{content:'hi'});
console.log(demo.provider('$say').content);
//hi
demo.provider('$say',{content:'hello'});
console.log(demo.provider('$say').content);
//hello
  • 当使用Provider时不要忘了把注册时的名字加到请求处理函数的参数列表里。
  • 不同请求之间共享一个Provider对象,同一请求的不同处理函数也共享同一个Provider对象。下面的例子可以较好地说明问题,当然你可以先阅读后面的章节handler再阅读这一部分内容。
jsdemo.provider('$count',{num:0});
demo.get('/count',function($scope,$count){
    $count.num++;
    $scope.send($count.num.toString()).end();
});
//you will get 1,2,3,4.. with client request '/count'
jsdemo.provider('$count',{num:0});
demo.handler('h0',function($scope,$count){
    $count.num++;
    $scope.go('next');
});
demo.handler('h1',function($scope,$count){
    $scope.send($count.num.toString()).end();
});
//you will get 1 instead of 0 when request '/count' for first time

suemi
1.5k 声望102 粉丝

程序猿一只,研究僧一枚