官方教程

Quick Start

按官方的Quick Start理解如下:
安装

npm install @feathersjs/feathers --save

服务端

创建一个类来管理一种资源,并且其同步async方法与REST的各种操作相对应,如messages资源。这个类称之为Service服务。

操作CRUD REST HTTP feathers class async 函数 完成事件
增 create POST async create(data, params) // 其中data为通过POST发送来的JSON,并且已经JSON.parse成了对象。params可选,下同 created
删 delete DELETE remove(id, params) removed
替换改 update PUT update(id, data, params) updated
合并改 update PATCH patch(id, data, params) patched
查所有 read GET messages async find(params) //返回值为GET的返回值,为JS对象。JSON化(JSON.stringify)由feathers完成,不需要我们操作 -
查部分 read GET mesages?xx=x&xxx=xx async get(id, params) {} -

另外有个查header的REST HEAD 似乎没有对应,这个命令和GET类似,只是不返回内容只返回header

class MessageService {
  //初始化时候需要创建一个存储资源的地方,示例中先在内存中建立了一个数组,后面估计可以改为数据库的访问
  constructor() { 
    this.messages = [];
  }

  async find () {
    // Just return all our messages
    return this.messages;
  }

  async create (data) {
    // The new message is the data merged with a unique identifier
    // using the messages length since it changes whenever we add one
    const message = {
      id: this.messages.length,
      text: data.text
    }

    // Add new message to the list
    this.messages.push(message); 

    return message;
  }
app.use('/messages', new MessageService());  // 这儿注册资源的url地址和资源的class服务

完整代码:

const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');

// A messages service that allows to create new
// and return all existing messages
class MessageService {
  constructor() {
    this.messages = [];
  }

  async find () {
    // Just return all our messages
    return this.messages;
  }

  async create (data) {
    // The new message is the data merged with a unique identifier
    // using the messages length since it changes whenever we add one
    const message = {
      id: this.messages.length,
      text: data.text
    }

    // Add new message to the list
    this.messages.push(message);

    return message;
  }
}

// Creates an ExpressJS compatible Feathers application 创建一个Express兼容的Feathers APP
const app = express(feathers());  

// Parse HTTP JSON bodies. 
// 从这儿开始注册中间件,先是自动对JSON数据解析的,也就是请求时header写着 ‘content-type: application/json’  的
app.use(express.json());
// Parse URL-encoded params 
// 解析 URL-encoded 格式的请求体数据,也就是请求时header写着‘content-type: application/x-www-form-urlencoded’ 的
app.use(express.urlencoded({ extended: true }));
// Host static files from the current folder
// 这个替代了nginx作用了,对.html .css等静态文件做http服务
app.use(express.static(__dirname));
// Add REST API support 
app.configure(express.rest());
// Configure Socket.io real-time APIs
app.configure(socketio());
// Register an in-memory messages service, 
// 这个是一句抵6句的REST注册了,否则要app.get/app.post/app.delete一个一个去搞定REST接口
app.use('/messages', new MessageService());
// Register a nicer error handler than the default Express one
app.use(express.errorHandler());

// Add any new real-time connection to the `everybody` channel 
// 一个连接connection类似一个会话session,一个频道channel类似MQTT的一个topic,
// 这儿在一个连接产生时将这个连接加入到everybody的频道中
app.on('connection', connection =>
  app.channel('everybody').join(connection)
);
// Publish all events to the `everybody` channel
// 一个事件events类似于MQTT的一个消息,当然这个events也是node的标准events,data是消息内容,
// publish的操作类似于MQTT的pub。sub操作是通过监听事件 .on 来做的,具体来说可以是监听created事件。
app.publish(data => app.channel('everybody'));

// Start the server
app.listen(3030).on('listening', () =>
  console.log('Feathers server listening on localhost:3030')
);

// For good measure let's create a message
// So our API doesn't look so empty 先自行加一条数据到messages资源中
app.service('messages').create({ 
  text: 'Hello world from the server'
});

客户端

直接访问http://localhost:3030/messages就相当于GET操作REST API
再创建一个index.html作为客户端来访问

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Feathers Example</title>
  <link rel="stylesheet" href="//unpkg.com/feathers-chat@4.0.0/public/base.css">
  <link rel="stylesheet" href="//unpkg.com/feathers-chat@4.0.0/public/chat.css">
</head>
<body>
  <main id="main" class="container">
    <h1>Welcome to Feathers</h1>
    <form class="form" onsubmit="sendMessage(event.preventDefault())">
      <input type="text" id="message-text" placeholder="Enter message here">
      <button type="submit" class="button button-primary">Send message</button>
    </form>

    <h2>Here are the current messages:</h2>
  </main>

  <script src="//unpkg.com/@feathersjs/client@^4.3.0/dist/feathers.js"></script>
  <script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.4/socket.io.js"></script>
  <script type="text/javascript">
    // Set up socket.io 实时连接监听地址
    const socket = io('http://localhost:3030');
    // Initialize a Feathers app
    const app = feathers();

    // Register socket.io to talk to our server
    app.configure(feathers.socketio(socket));

    // Form submission handler that sends a new message
    async function sendMessage () {
      const messageInput = document.getElementById('message-text');

      // Create a new message with the input field value, 通过REST POST发送消息,当然这一切都隐藏了
      await app.service('messages').create({
        text: messageInput.value
      });

      messageInput.value = '';
    }

    // Renders a single message on the page,增加一条新的message
    function addMessage (message) {
      document.getElementById('main').innerHTML += `<p>${message.text}</p>`;
    }

    const main = async () => {
      // Find all existing messages
      const messages = await app.service('messages').find();

      // Add existing messages to the list
      messages.forEach(addMessage);

      // Add any newly created message to the list in real-time
      app.service('messages').on('created', addMessage);
    };

    main();
  </script>
</body>
</html>

除了REST以外的概念

如果只是实现REST就不想要下面这些了

实时通讯

类似MQTT咯。REST只能根据客户端的请求相应,而实时通讯可以根据事件主动向客户端推送消息
Channels 实时通讯通道,类似于MQTT的topic吧
Events 事件系统

使用cli构建

安装cli: npm install @feathersjs/cli -g
使用cli

mkdir feathers-chat
cd feathers-chat/
feathers generate app

交互式命令行输出:

D:\r\feathers_proj\feather-chat>feathers generate app
? Do you want to use JavaScript or TypeScript? JavaScript
? Project name feather-chat
? Description
? What folder should the source files live in? src
? Which package manager are you using (has to be installed globally)? npm
? What type of API are you making? REST, Realtime via Socket.io
? Which testing framework do you prefer? Mocha + assert
? This app uses authentication Yes
? Which coding style do you want to use? ESLint
? What authentication strategies do you want to use? (See API docs for all 180+ supported oAuth providers) Username + Pa
ssword (Local)
? What is the name of the user (entity) service? users
? What kind of service is it? NeDB
? What is the database connection string? nedb://../data
   create package.json
   create config\default.json
   create public\favicon.ico
   create public\index.html
   create .editorconfig
   create src\app.hooks.js
   create src\channels.js
   create src\index.js
   create src\logger.js
   create src\middleware\index.js
   create src\services\index.js
   create .gitignore
   create README.md
   create src\app.js
   create test\app.test.js
   create .eslintrc.json
   create config\production.json
   create config\test.json
   create src\services\users\users.service.js
   create src\authentication.js
   create test\authentication.test.js
   create src\services\users\users.class.js
   create src\models\users.model.js
   create src\services\users\users.hooks.js
   create test\services\users.test.js
.....

目录简述

  • config/ 配置
  • public/ html静态文件,大概意思是nginx都不用装了
  • src/ 源码。包括hooks钩子和services服务。services里默认有一个users服务。
  • middleware/ 放express的中间件
  • models/ 放数据库模型,也就是和数据库的链接映射。里面默认有一个users.model.js提供与users表的映射
  • test/ 测试

根目录文件简述

  • app.js feathers应用的配置
  • app.hooks.js app的钩子
  • authentication.js 认证系统
  • channels.js 频道系统,用于实时通讯
  • index.js 入口

运行命令

# 启动
npm start
# 测试
npm test
# 开发模式,代码更新自动重运行
npm run dev

通过cli创建services

feathers generate service

通过cli交互创建需要的文件

λ feathers generate service                                                                                                                                         
? What kind of service is it? NeDB                                                                                                                                  
? What is the name of the service? messages                                                                                                                         
? Which path should the service be registered on? /messages                                                                                                         
? Does the service require authentication? Yes                                                                                                                      
   create src\services\messages\messages.service.js                                                                                                                 
    force src\services\index.js                                                                                                                                     
   create src\services\messages\messages.class.js                                                                                                                   
   create src\models\messages.model.js                                                                                                                              
   create src\services\messages\messages.hooks.js                                                                                                                   
   create test\services\messages.test.js                                                                                                                            
npm WARN ws@7.4.6 requires a peer of bufferutil@^4.0.1 but none is installed. You must install peer dependencies yourself.                                          
npm WARN ws@7.4.6 requires a peer of utf-8-validate@^5.0.2 but none is installed. You must install peer dependencies yourself.                                      
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.2 (node_modules\fsevents):                                                                             
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})   

up to date in 8.347s                                                                                                                                                
npm WARN ws@7.4.6 requires a peer of bufferutil@^4.0.1 but none is installed. You must install peer dependencies yourself.                                          
npm WARN ws@7.4.6 requires a peer of utf-8-validate@^5.0.2 but none is installed. You must install peer dependencies yourself.                                      
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.2 (node_modules\fsevents):                                                                             
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})   

up to date in 4.056s                                                                                                                                                

基本是创建了src/services目录下的三个文件,挂载到index.js上,并创建连接数据库的对应model.js和测试文件

Hooks钩子

钩子可以在服务的前、后、错误时运行。钩子与服务是多对多的关系,相当于对多个不同服务中类似的功能提取公因数。

const createdAt = async context => {
  context.data.createdAt = new Date();

  return context;
};

app.service('messages').hooks({
  before: {
    create: [ createdAt ]
  }
});

Cli方式创建钩子

命令是:

feathers generate hook                                                          

交互示意:

λ feathers generate hook                                                          
? What is the name of the hook? process-message                                   
? What kind of hook should it be? before                                          
? What service(s) should this hook be for (select none to add it yourself)?       
 messages                                                                         
? What methods should the hook be for (select none to add it yourself)? create    
   create src\hooks\process-message.js                                            
    force src\services\messages\messages.hooks.js                                 

标签: none 阅读量: 1589

添加新评论