Feathers框架 1:Guides --> Basics

https://docs.feathersjs.com/guides/basics/readme.html

1.1、The Basics

    Setting up:安装

$ mkdir feathers-basics

$ npm init --yes  #默认初始化

$ npm install @feathersjs/feathers --save #安装feathers

$ node app.js 

const feathers = require('@feathersjs/feathers');
const app = feathers();
// Register a simple todo service that return the name and a text
app.use('todos', {
	async get(name) {
		return {
			name,
			text: 'You have to do ${name}'
		};
	}
});
// A function that gets and logs a todo from the service
async function getTodo(name) {
	const service = app.service('todos');
	// Call the 'get' method with a name
	const todo = await service.get(name);
	// Log the todo we got back
	console.log(todo);
}
getTodo('dishes');
$ node app.js 
{ name: 'dishes', text: 'You have to do ${name}' }
      In the browser

$ mkdir public

$ npm install http-server -g

$ http-server public/

$ subl public/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Feathers Basics</title>
</head>
<body>
  <h1>Welcome to Feathers</h1>
  <p>Open up the console in your browser.</p>
  <script type="text/javascript" src="//unpkg.com/@feathersjs/client@^3.0.0/dist/feathers.js"></script>
  <script src="client.js"></script>
</body>
</html>

$ subl public/client.js

const app = feathers();

// Register a simple todo service that return the name and a text
app.use('todos', {
  async get(name) {
    // Return an object in the form of { name, text }
    return {
      name,
      text: `You have to do ${name}`
    };
  }
});

// A function that gets and logs a todo from the service
async function logTodo(name) {
  // Get the service we registered above
  const service = app.service('todos');
  // Call the `get` method with a name
  const todo = await service.get(name);

  // Log the todo we got back
  console.log(todo);
}

logTodo('dishes');
http://127.0.0.1:8080/

    Services:the heart of every Feathers application and JavaScript objects or instances of a class that implement certain methods. Services provide a uniform, protocol independent interface for how to interact with any kind of data like: ... 

     Protocol independent means that to a Feathers service it does not matter if it has been called internally, through a REST API or websockets.

      Service methods are CRUD methods that a service object can implement.
      A messages services :  app.js

const feathers = require('@feathersjs/feathers');
class Messages {
	constructor() {
		this.messages = [];
		this.currentId = 0;
	}
	async find(params) {
		// Return the list of all messages
		return this.messages;
	}
	async get(id, params) {
		//Find the message by id
		const message = this.messages.find(message => message.id === parseInt(id, 10));
		// Throw an error if it wasn't found
		if (!message) {
			throw new Error('Message with id ${id} not found');
		}
		// Otherwise return the message
		return message;
	}
	async create(data, params) {
		// Create a new object with the original data and an id 
		// taken from the incrementing 'currentId' counter
		const message = Object.assign({
			id : ++this.currentId
		}, data);
		this.messages.push(message);
		return message;
	}
	async path(id, data, params) {
		// Get the existing message. Will throw an error if not found
		const message = await this.get(id);
		// Merge the existing message with the new data
		// and return the result
		return Object.assign(message, data);
	}
	async remove(id, params) {
		const message = await this.get(id);
		const index = this.messages.indexOf(message);
		this.messages.splice(index, 1);
		return message;
	}
}
const app = feathers();
//启用Services
app.use('messages', new Messages());

//Using Services
async function processMessages() {
	await app.service('messages').create({
		text: 'First message'
	});
	await app.service('messages').create({
		text: 'Second message'
	});
	const messageList = await app.service('messages').find();
	console.log('Available messages', messageList);
}

processMessages();
     $ node app.js 
Available messages [ { id: 1, text: 'First message' },
  { id: 2, text: 'Second message' } ]
     Service events : Events can be listened to with app.service('messages').on('eventName', data => {}).

//Using Services
async function processMessages() {
	app.service('messages').on('created', message => {
		console.log('Created a new message', message);
	});
	app.service('messages').on('removed', message => {
		console.log('Deleted message', message);
	});
	await app.service('messages').create({
		text: 'First message'
	});

	const lastMessage = await app.service('messages').create({
		text: 'Second message'
	});
	await app.service('messages').remove(lastMessage.id);
	const messageList = await app.service('messages').find();
	console.log('Available messages', messageList);
}
     $ node app.js 
Created a new message { id: 1, text: 'First message' }
Created a new message { id: 2, text: 'Second message' }
Deleted message { id: 2, text: 'Second message' }
Available messages [ { id: 1, text: 'First message' } ]
      Hooks:pluggable middleware functions that can be registered before, after or on errors of a service method. You can register a single hook function or create a chain of them to create complex work-flows.

      Hookes are commonly used to handle things like validation, authorization, logging, populating related entities, sending notifications and more.


const messagesHooks = {
  before: {
    all: [ hook01() ],
    find: [ hook11() ],
    get: [ hook21() ],
    create: [ hook31(), hook32() ],
    update: [ hook41() ],
    patch: [ hook51() ],
    remove: [ hook61() ],
  },
  after: {
    all: [ hook05() ],
    find: [ hook15(), hook16() ],
    create: [ hook35() ],
    update: [ hook45() ],
    patch: [ hook55() ],
    remove: [ hook65() ],
  }
};

app.service('messages').hooks(messagesHooks);
     If a hook throws an error, all following hooks will be skipped and the error will be returned to the user. 
     $ npm install @feathersjs/errors --save

const { BadRequest} = require('@feathersjs/errors');
const validate = async context => {
	const { data } = context;
	// Check if there is 'text' property
	if (!data.text) {
		throw new BadRequest('Message text must exist');
	}
	// Check if it is a string and not just whitespace
	if (typeof data.text !== 'string' || data.text.trim() === '') {
		throw new BadRequest('Message text is invalid');
	}
	//
	context.data = {
		text: data.text.toString(),
	}
	return context;
};
app.service('messages').hooks({
	before: {
		create: validate,
		update: validate,
		patch: validate
	}
});
     A good use for application hooks is to log my service method call error. 
      REST APIs : Currently Feathers officially has three transports :

  • HTTP REST via Express for exposing services through a JSON REST API
  • Socket.io for connecting to services through websockets and also receiving real-time service events
  • Primus an alternative to Socket.io supporting several websocket protocols which also supports real-time events


      What the Feathers REST transport essentially does is to automatically map our existing service methods to those endpoints.

      Express integration : You can use Feathers functionality like services but also any existing Express middleware. 

    $ npm install @feathersjs/express --save 

const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
class Messages {
	constructor() {
		this.messages = [];
		this.currentId = 0;
	}
	async find(params) {
		// Return the list of all messages
		return this.messages;
	}
	async get(id, params) {
		//Find the message by id
		const message = this.messages.find(message => message.id === parseInt(id, 10));
		// Throw an error if it wasn't found
		if (!message) {
			throw new Error('Message with id ${id} not found');
		}
		// Otherwise return the message
		return message;
	}
	async create(data, params) {
		// Create a new object with the original data and an id 
		// taken from the incrementing 'currentId' counter
		const message = Object.assign({
			id : ++this.currentId
		}, data);
		this.messages.push(message);
		return message;
	}
	async path(id, data, params) {
		// Get the existing message. Will throw an error if not found
		const message = await this.get(id);
		// Merge the existing message with the new data
		// and return the result
		return Object.assign(message, data);
	}
	async remove(id, params) {
		const message = await this.get(id);
		const index = this.messages.indexOf(message);
		this.messages.splice(index, 1);
		return message;
	}
}
// const app = feathers();
//启用Services
//app.use('messages', new Messages());
// This creates an app that is both, an Express and Feathers app
const app = express(feathers());
// Turn on JSON body parsing for REST services
app.use(express.json());
// Turn on URL-encoded body parsing for REST services
app.use(express.urlencoded({ extended: true }));
// Set up REST transport using Express
app.configure(express.rest())

app.use('messages', new Messages()); // --->

// Set up an error handler that gives us nicer errors
app.use(express.errorHandler());
const server = app.listen(3030);

app.service('messages').create({
	text: 'Hello from the server'
});
server.on('listening', () => console.log('Feathers REST API started at localhost:3030'));
    $ node app.js 
Feathers REST API started at localhost:3030

http://localhost:3030/messages

$ curl 'http://localhost:3030/messages/' -H 'Content-Type: application/json' --data-binary '{ "text": "Hello from the command line!" }'

$  curl -X "DELETE" http://localhost:3030/messages/1        
    Databases : Feathers has a collection of pre-built services for different databases. 


 Tip: Each one of the linked adapters has a complete REST API example in their readme.

   $ npm install feathers-memory --save

app.use('messages', memory({
	paginate: {
		default: 10,
		max: 25
	}
}));
      Querying : all database adapters support a common way of querying the data in a find method call using params.query. 
async function createAndFind() {
  const messages = app.service('messages');
  for (let counter=0; counter<100; counter++) {
    await messages.create({
      counter,
      message: 'Message number ${counter}'
    });
  }
  // we show 10 entries by default, By skipping 10 we go to page 2
  const page2 = await messages.find({
    query: { $skip: 10 }
  });
  console.log('Page number 2', page2);
  // Show 20 items per page
  const largePage = await messages.find({
    query: { $limit: 20 }
  });
  console.log('20 items', largePage);
  // Find the first 10 items with counter greater 50 and less than 70
  const counterList = await messages.find({
    query: {
      counter: { $gt: 50, $lt: 70 }
    }
  });
  console.log('Counter greater 50 and less than 70', counterList);
  // Find all entries with text "message number 20"
  const message20 = await messages.find({
    query: {
      message: 'Message number 20'
    }
  });
  console.log('Entries with text "Message number 20"', message20);
}
createAndFind();
     As a REST API : Using a database adapter instead will make our app.js a lot shorter.

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

// This creates an app that is both, an Express and Feathers app
const app = express(feathers());
// Turn on JSON body parsing for REST services
app.use(express.json());
// Turn on URL-encoded body parsing for REST services
app.use(express.urlencoded({ extended: true }));
// Set up REST transport using Express
app.configure(express.rest())
// Set up an error handler that gives us nicer errors
app.use(express.errorHandler());
app.use('messages', memory({
	paginate: {
		default: 10,
		max: 25
	}
}));
const server = app.listen(3030);
app.service('messages').create({
	text: 'Hello from the server'
});
server.on('listening', () => console.log('Feathers REST API started at localhost:3030'));
http://localhost:3030/messages?$limit=2
      Real-Time APIs : means that those events are also published to connected clients so that they can react accordingly, e.g. update their UI.

Important: The REST transport does not support real-time updates. Since socket transport also allow to call service methods and generally perform better, we recommend using a real-time transport whenever possible.

   $ npm install @feathersjs/socketio --save    

const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');
const app = express(feathers());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Set up REST transport using Express
app.configure(express.rest());
app.use(express.errorHandler());
// Configure the Socket.io transport
app.configure(socketio);
app.listen(3030);
      Channels : determine which real-time events should be sent to which client. For example, we want to only send messages to authenticated users or users in the same room. For this example we will just enable real-time functionality for all connections 
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');
const memory = require('feathers-memory');
const app = express(feathers());
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
// Set up REST transport using Express
app.configure(express.rest());
// Configure the Socket.io transport
app.configure(socketio);
// On any real-time connection, add it to the 'everybody' channel
app.on('connection', connection => app.channel('everybody').join(connection));
// Publish all events to the 'everybody' channel
app.publish( () => app.channel('everybody') );
// Initialize the messages service
app.use('messages', memory({
	paginate: {
		default: 10,
		max: 25
	}
}));
app.use(express.errorHandler());
const server = app.listen(3030);
server.on('listening', ()=> console.log('Feathers API started at localhost:3030'));
    public/client.js

const app = feathers();

app.use('messages', memory({
  paginate: {
    default: 10,
    max: 25
  }
}));

const socket = io('http://localhost:3030');
socket.on('messages created', message => 
   console.log('Someone created a message', message)
);

socket.emit('create', 'messages', {
  text: 'Hello from socket'
}, (error, result) => {
  if (error) throw error 
    socket.emit('find', 'messages', (error, messageList) => {
      if (error) throw error
      console.log('Current messages', messageList);
  });
});
      The Feathers generator (CLI)

    $ npm install @feathersjs/cli -g

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值