原文地址javascript
近年来NODEJS发展迅速,不少工程师尤为是前端工程师,用NODEJS来开发一些后端应用。同时,研发效率和研发成本成为开发者关注的重点,对于一些基础经常使用功能,如何避免重复开发,成为你们关注的重点,而 Parse Server 就是抽象了经常使用功能的NODEJS开源项目。html
首先,从总体上看看 Parse Server
提供了哪些基础功能:前端
默认状况下,Parse Server 使用的默认数据库是 MonogDB
,因此须要提早安装该数据库。关于数据库的安装与使用不是本文的重点,暂且跳过。java
const config = require('./config'); const app = express(); var api = new ParseServer({ databaseURI: config.databaseURI, cloud: './cloud/main.js', appId: config.appId, masterKey: config.masterKey, // push: { ... }, // See the Push wiki page // filesAdapter: ..., // 对应不一样云厂商的 FilesAdapter // javascriptKey: config.javascriptKey, // js客户端认证 liveQuery: { // 创建websocket连接,实现实时通讯 classNames: ['Sdtuent'] } }); var dashboard = new ParseDashboard({ "apps": [ { "serverURL": "http://localhost:1337/parse", "appId": config.appId, "masterKey": config.masterKey, "appName": "test" }, ] }); // Serve the Parse API at /parse URL prefix app.use('/parse', api); app.use('/dashboard', dashboard); const port = 1337; const httpServer = http.createServer(app); httpServer.listen(port, function() { console.log('parse-server-example running on port ' + port + '.'); }); var parseLiveQueryServer = ParseServer.createLiveQueryServer(httpServer);
经过上述少许的代码,快速完成服务的搭建,/parse
是API的前缀,/dashboard
是后台的页面路由前缀,这样就能够快速使用 Parse Server 提供的各类功能。git
针对不一样环境、不一样语言,parse server提供了大量的 SDK,本文以 javascript
为例进行简单介绍。github
<head> <script src="https://unpkg.com/parse@2.1.0/dist/parse.js"></script> </head> <body> ... <script> // 对应服务端设置的id Parse.initialize(${appId}, ${javascriptKey}); Parse.serverURL = 'http://127.0.0.1:1337/parse' const username = "xxx", password = 'xxxx'; const email = 'xxx' async function signup() { try { const user = new Parse.User; user.set('username', username); user.set('password', password); user.set('email', email); const result = await user.signUp(); console.log('result is: ', result); } catch(err) { console.log('error: ', err); } } signup(); </script> </body>
上面的示例,是在浏览器端进行用户的注册: 首先引入Javascript SDK
;而后进行基本的环境设置 Parse.initialize
、Parse.serverURL
;第三部就是使用SDK调用 user.signUp
完成注册。web
而后到 dashboard
,能够看到 user
中新增了一条记录:数据库
{ "results": [ { "objectId": "1r2sFIzSRP", "username": "xxx", "createdAt": "2019-02-16T10:30:00.070Z", "updatedAt": "2019-02-16T10:30:00.070Z", "ACL": { "*": { "read": true }, "1r2sFIzSRP": { "read": true, "write": true } } } ] }
Parse Server的权限控制分为两层: Class level permission(类级别的权限控制)、Object level access control(对象级别的权限控制)。express
async function saveData() { const Student = Parse.Object.extend("Student"); const student = new Student(); student.setACL(new Parse.ACL(Parse.User.current())); student.set("name", "小明"); student.set("age", 12); const result = await student.save(); console.log('save data: ', result); } async function getData() { const Student = Parse.Object.extend("Student"); const query = new Parse.Query(Student); query.equalTo('name', '小明'); const result = await query.find(); console.log('save data: ', result); } async function run() { await saveData(); await getData(); // 得到一条数据 await Parse.User.logOut(); // 用另一个帐号登陆 await getData(); // 结果为空 }
上述示例设置了 Object level access control
,只有拥有该 object
权限的用户,才能获取对应的数据。后端
要实现数据的实时通讯,一般的作法是搭建一个websocket服务,客户端与服务端创建长链接,这样就能够实现数据的实时通讯。Parse Server
也集成了这个功能,把websocket服务跟HTTP服务整合在一块儿,便于 client 端统一调用。
由于 Parse Server 背后的数据存储使用的是 MongoDB,数据格式是 schemaless 的, 可是这并非说能够随意写入数据:
Class
的时候,能够自定义字段及类型,同时默认添加 _id、_created_at、_updated_at、_acl 等字段_SCHEMA
集合,存储了 Class 的格式信息,约束了数据再次写入时的字段类型为了验证上述两点,直接登陆 MongoDB
数据库后台:
// step1: 登陆数据库后台 mongo // step2: 查看 collection 状况 show collections 结果以下: Student _Role _SCHEMA _Session _User // step3: 查看 _SCHEMA 内容 db.getCollection('_SCHEMA').find() 结果以下: { "_id":"Student", "objectId":"string", "updatedAt":"date", "createdAt":"date", "name":"string", "age":"number", "address":"string" } ...
接下来对Student表进行写入操做,age的类型不是number,而使用string:
async function saveData() { const Student = Parse.Object.extend("Student"); const student = new Student(); student.setACL(new Parse.ACL(Parse.User.current())); student.set("name", "张三"); student.set("age", '9999'); student.set('address', '北京'); const result = await student.save(); console.log('save data: ', result); }
执行上述代码,会抛出异常信息 schema mismatch for Student.age; expected Number but got String
若是进行业务开发,确定存在自定义的业务逻辑,Parse Server 一样提供了对应的解决途径。
先来看看 Cloud Code 是如何工做的:
// step1 在Parse Server入口处指定路径 var api = new ParseServer({ ... cloud: './cloud/main.js', ... }); // step2 定义通常的Function Parse.Cloud.define("averageStars", async (request, response) => { const params = request.params; ... const result = ... response.success(result); }); // 定义hook函数 Parse.Cloud.beforeSave("Student", (request) => { ... }); // step3 客户端调用自定义函数方式 async function invokeFn() { const params = { ... }; const ratings = await Parse.Cloud.run("averageStars", params); console.log('ratings: ', ratings); } // 客户端出发hook比较简单,对Student进行写入,就会触发hook函数 async function saveData() { const Student = Parse.Object.extend("Student"); const student = new Student(); ... const result = await student.save(); }
同时,Parse Server 也支持远程调用,使用 Dashboard 的 Webhook功能,就能够配置远程调用API
Parse Server这个开源项目给了很多项目设计上的思考: