使用react native 创建一个属于你自己的云备忘录app~(A。用node搭个服务,基础篇)

前言

写这个的初衷是由于现在的记事本app都太冗余了,我很喜欢google的keep,但要是想同步的话还要翻墙;有道云笔记又有些大,ui也不够直观,太办公向了,写博客我很喜欢,但随手写点备忘录,还是显得有点重。正好我使用react native也有一段时间了,学node一直也找不到自己喜欢的项目练手,不如就自己写一个吧~

在写这个项目之前,可以说一点都不了解mongoDB,不了解他的数据结构;可以说是一个完全的后端小白了。。

如果对这个项目有兴趣的朋友可以在github上点下star,本人也会一直更新迭代~有疑问和建议的朋友可以在评论区指出 ~嘻嘻

起步

先建个服务

// server.js
const express=require('express')
const app=express()

// 用于上传笔记
app.get('/upload',(req,res)=>{
    res.send('uploaded!!')
})

const server=app.listen(8888,()=>{
    const host=server.address().address
    const port=server.address().port

    console.log(`the server is listening on ${host}:${port}`)
})

初始化路由

基本上有三个路由,上传,删除,查找

// server.js

// 上传文章
app.get('/upload', (req, res) => {
  res.send('uploaded!!');
});

// 删除文章
app.get('/delete', (req, res) => {
  res.send('delete!!');
});

// 按分类查找
app.get('/findByLabel', (req, res) => {
  res.send('findByLabel!!');
});

初始化数据库

数据库使用mongodb,我用的是node-mongodb-native作为引擎他是mongodb官方的node引擎,express官网上推荐的mongoskin,有一年多没更新了就放弃了。

新建一个数据库配置文件,

const { MongoClient } = require('mongodb');
const assert = require('assert');

// Connection URL
const url = 'mongodb://localhost:27017';

// Database Name
const dbName = 'memo';

function connectDB() {
  // Use connect method to connect to the server
  MongoClient.connect(url, (err, client) => {
    assert.equal(null, err);
    console.log('Connected successfully to server');

    const db = client.db(dbName);

    client.close();
  });
}

module.exports = { connectDB };

在server.js中引用这个模块,启动服务后,终端打印了Connected successfully to server,即为连接成功。

自定义配置

将配置信息单独放在一个文件夹中,方便维护。这里写入了监听端口和数据库信息,如果有其他的,将在后面加入。

module.exports = {
  port: 8888,
  mongodb: 'mongodb://localhost:27017',
  dbName: 'memo',
};

使用promise重构连接数据库方法

查看了文档,因为其他操作数据库的api都依赖于MongoClient.connect方法中的回调函数中的参数client。因为操作数据库复杂,为了使代码更清晰,同时避免回调地狱,使用promise做个封装,进行链式调用。

// mongo.js
const connectDB = new Promise((resolve, reject) => {
  MongoClient.connect(mongodbURL, (err, client) => {
    if (err) {
      reject(err);
    } else {
      assert.equal(null, err);
      console.log('Connected successfully to server');

      const db = client.db(dbName);
      resolve(db);
    }
  });
});

module.exports = { connectDB };

调用:

connectDB.then((db) => {
  findDocuments(db);
});

编写添加方法

基础模板

const assert = require('assert');

const insertDocuments = function (db, callback = () => {}) {
  // Get the documents collection
  const collection = db.collection('documents');
  // Insert some documents
  collection.insertOne({ a: 'test' }, (err, result) => {
    assert.equal(err, null);
    assert.equal(1, result.result.n);
    assert.equal(1, result.ops.length);
    console.log('Inserted a document into the collection');
    callback(result);
  });
};

module.exports = { insertDocuments };

其他的操作,如删除或查找,都可以在官方文档上都可以找到,就不一一举例了。

创建错误实例

包括一个请求状态码和错误码

// createError.js
function createError(code = 1) {
  return {
    status: 1,// 1为错误;0为成功
    code,
  };
}

module.exports = { createError };

我们再编写几个可能会出现的错误实例,如:

// error.js
const errors = {
  CONNECT_DB_FAILED: 'CONNECT_DB_FAILED', // 连接数据库失败

};

稍微更改下connectDB的逻辑:

const connectDB = new Promise((resolve, reject) => {
  MongoClient.connect(mongodbURL, (err, client) => {
    if (err) {
      reject(createError(errors.CONNECT_DB_FAILED));
    } else {
      const db = client.db(dbName);
      resolve(db);
    }
  });
});

尝试把config.js中的mongodbURL更改为错误的地址,查看终端是否打印{ status: 1, code: 'CONNECT_DB_FAILED' }

用promise封装添加方法

由于官方给出的代码例子都是回调形式,代码意图不清晰,使用promise封装,避免回调地狱。

const insertDocuments = (db, data = { test: 1 }, collectionName = 'documents') => new Promise((resolve, reject) => {
  const collection = db.collection(collectionName);
  collection.insertOne(data, (err, { result }) => {
    if (err) {
      reject(createError(errors.HANDLE_DB_FAILED));
    } else {
      resolve(createResult(result));
    }
  });
});

在index.js中,更改调用方式,终端会打印data { status: 0, body: { n: 1, ok: 1 } }

connectDB
  .then(db => insertDocuments(db))
  .then(data => console.log('data', data))
  .catch((err) => {
    console.log(err);
  });

解析请求

我们发送的请求中的数据,要放到req.body中去接收,这里需要安装express的中间件bodyParser

const bodyParser = require('body-parser');
app.use(bodyParser.json({ extended: true }));

使用postman测试一下,发送请求{{URL}}/upload,body中写入

{
    "context":"hello world"
}

我们编写一下upload函数,来打印一下

function upload(req, res) {
  const { context } = req.body;
  console.log(context) // hello world
  res.send('uploaded!!');
}

控制台有输出,则成功。

之后,把之前写好的上传函数写入upload中。

function upload(req, res) {
  const { context } = req.body;
  connectDB
    .then(db => insertDocuments(db, context))
    .then(data => console.log('data', data))
    .catch((err) => {
      console.log(err);
    });
  res.send('uploaded!!');
}

执行正常,则会返回{ status: 0, body: { n: 1, ok: 1 } }

错误实例分类

在请求的过程中,可能会发生网络错误、数据库错误或是接口参数错误;如果单纯的返回一个错误状态,整个服务就显得太不可靠了。

在constants文件夹下创建一个错误常量的对象,在后续的开发过程中我们将加入更多的错误类型,先简单写这几个

const errors = {
  CONNECT_DB_FAILED: 'CONNECT_DB_FAILED', // 连接数据库失败
  HANDLE_DB_FAILED: 'HANDLE_DB_FAILED', // 与数据库操作时发生错误
  INVALID_PARAMETERS: 'INVALID_PARAMETERS', // 参数错误
  SYSTEM_ERROR: 'SYSTEM_ERROR', // 系统错误,可能是语法,查看日志

};

module.exports = errors;

然后,我们再创建几个错误处理函数,用于把错误类型传递到响应参数中。如下:

function parameterInvalid(res) {
  res.json(createError(INVALID_PARAMETERS));
}

function unknowError(err, res) {
  console.log(err);
  res.json(createError(SYSTEM_ERROR));
}

module.exports = { parameterInvalid, unknowError };

把上面的函数写进upload方法中:

const { parameterInvalid, unknowError } = require('../lib/handleErrors');

function upload(req, res) {
  const { context } = req.body;
  if (!context) {
    parameterInvalid(res);
    return;
  }

  connectDB
    .then(db => insertDocuments(db, { context }))
    .then(data => res.json(data))
    .catch((err) => { unknowError(err, res); });
}

以上,一个基础的上传服务就完成了~~ 还有其他的操作,如删除、更新等,其实都大同小异,区别于node-mongo的api,大家可以查阅官方文档或是查看项目源代码~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,830评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,992评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,875评论 0 331
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,837评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,734评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,091评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,550评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,217评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,368评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,298评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,350评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,027评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,623评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,706评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,940评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,349评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,936评论 2 341

推荐阅读更多精彩内容