使用react native 創(chuàng)建一個(gè)屬于你自己的云備忘錄app~(A腰吟。用node搭個(gè)服務(wù)无埃,基礎(chǔ)篇)

前言

寫這個(gè)的初衷是由于現(xiàn)在的記事本app都太冗余了徙瓶,我很喜歡google的keep,但要是想同步的話還要翻墻嫉称;有道云筆記又有些大侦镇,ui也不夠直觀,太辦公向了织阅,寫博客我很喜歡壳繁,但隨手寫點(diǎn)備忘錄,還是顯得有點(diǎn)重荔棉。正好我使用react native也有一段時(shí)間了闹炉,學(xué)node一直也找不到自己喜歡的項(xiàng)目練手,不如就自己寫一個(gè)吧~

在寫這個(gè)項(xiàng)目之前润樱,可以說一點(diǎn)都不了解mongoDB渣触,不了解他的數(shù)據(jù)結(jié)構(gòu);可以說是一個(gè)完全的后端小白了壹若。嗅钻。

如果對(duì)這個(gè)項(xiàng)目有興趣的朋友可以在github上點(diǎn)下star,本人也會(huì)一直更新迭代~有疑問和建議的朋友可以在評(píng)論區(qū)指出 ~嘻嘻

起步

先建個(gè)服務(wù)

// 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}`)
})

初始化路由

基本上有三個(gè)路由店展,上傳养篓,刪除,查找

// 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!!');
});

初始化數(shù)據(jù)庫

數(shù)據(jù)庫使用mongodb壁查,我用的是node-mongodb-native作為引擎他是mongodb官方的node引擎,express官網(wǎng)上推薦的mongoskin剔应,有一年多沒更新了就放棄了睡腿。

新建一個(gè)數(shù)據(jù)庫配置文件,

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中引用這個(gè)模塊,啟動(dòng)服務(wù)后峻贮,終端打印了Connected successfully to server席怪,即為連接成功。

自定義配置

將配置信息單獨(dú)放在一個(gè)文件夾中纤控,方便維護(hù)挂捻。這里寫入了監(jiān)聽端口和數(shù)據(jù)庫信息,如果有其他的船万,將在后面加入刻撒。

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

使用promise重構(gòu)連接數(shù)據(jù)庫方法

查看了文檔,因?yàn)槠渌僮鲾?shù)據(jù)庫的api都依賴于MongoClient.connect方法中的回調(diào)函數(shù)中的參數(shù)client耿导。因?yàn)椴僮鲾?shù)據(jù)庫復(fù)雜声怔,為了使代碼更清晰,同時(shí)避免回調(diào)地獄舱呻,使用promise做個(gè)封裝醋火,進(jìn)行鏈?zhǔn)秸{(diào)用。

// 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 };

調(diào)用:

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

編寫添加方法

基礎(chǔ)模板

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 };

其他的操作,如刪除或查找芥驳,都可以在官方文檔上都可以找到柿冲,就不一一舉例了。

創(chuàng)建錯(cuò)誤實(shí)例

包括一個(gè)請(qǐng)求狀態(tài)碼和錯(cuò)誤碼

// createError.js
function createError(code = 1) {
  return {
    status: 1,// 1為錯(cuò)誤兆旬;0為成功
    code,
  };
}

module.exports = { createError };

我們?cè)倬帉憥讉€(gè)可能會(huì)出現(xiàn)的錯(cuò)誤實(shí)例假抄,如:

// error.js
const errors = {
  CONNECT_DB_FAILED: 'CONNECT_DB_FAILED', // 連接數(shù)據(jù)庫失敗

};

稍微更改下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更改為錯(cuò)誤的地址,查看終端是否打印{ status: 1, code: 'CONNECT_DB_FAILED' }爵憎。

用promise封裝添加方法

由于官方給出的代碼例子都是回調(diào)形式慨亲,代碼意圖不清晰,使用promise封裝宝鼓,避免回調(diào)地獄刑棵。

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中,更改調(diào)用方式愚铡,終端會(huì)打印data { status: 0, body: { n: 1, ok: 1 } }蛉签。

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

解析請(qǐng)求

我們發(fā)送的請(qǐng)求中的數(shù)據(jù),要放到req.body中去接收沥寥,這里需要安裝express的中間件bodyParser

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

使用postman測(cè)試一下碍舍,發(fā)送請(qǐng)求{{URL}}/upload,body中寫入

{
    "context":"hello world"
}

我們編寫一下upload函數(shù)邑雅,來打印一下

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

控制臺(tái)有輸出片橡,則成功。

之后淮野,把之前寫好的上傳函數(shù)寫入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!!');
}

執(zhí)行正常,則會(huì)返回{ status: 0, body: { n: 1, ok: 1 } }

錯(cuò)誤實(shí)例分類

在請(qǐng)求的過程中骤星,可能會(huì)發(fā)生網(wǎng)絡(luò)錯(cuò)誤经瓷、數(shù)據(jù)庫錯(cuò)誤或是接口參數(shù)錯(cuò)誤;如果單純的返回一個(gè)錯(cuò)誤狀態(tài)洞难,整個(gè)服務(wù)就顯得太不可靠了舆吮。

在constants文件夾下創(chuàng)建一個(gè)錯(cuò)誤常量的對(duì)象,在后續(xù)的開發(fā)過程中我們將加入更多的錯(cuò)誤類型队贱,先簡(jiǎn)單寫這幾個(gè)

const errors = {
  CONNECT_DB_FAILED: 'CONNECT_DB_FAILED', // 連接數(shù)據(jù)庫失敗
  HANDLE_DB_FAILED: 'HANDLE_DB_FAILED', // 與數(shù)據(jù)庫操作時(shí)發(fā)生錯(cuò)誤
  INVALID_PARAMETERS: 'INVALID_PARAMETERS', // 參數(shù)錯(cuò)誤
  SYSTEM_ERROR: 'SYSTEM_ERROR', // 系統(tǒng)錯(cuò)誤色冀,可能是語法,查看日志

};

module.exports = errors;

然后柱嫌,我們?cè)賱?chuàng)建幾個(gè)錯(cuò)誤處理函數(shù)呐伞,用于把錯(cuò)誤類型傳遞到響應(yīng)參數(shù)中。如下:

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

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

module.exports = { parameterInvalid, unknowError };

把上面的函數(shù)寫進(jìn)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); });
}

以上慎式,一個(gè)基礎(chǔ)的上傳服務(wù)就完成了~~ 還有其他的操作伶氢,如刪除趟径、更新等,其實(shí)都大同小異癣防,區(qū)別于node-mongo的api蜗巧,大家可以查閱官方文檔或是查看項(xiàng)目源代碼~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蕾盯,隨后出現(xiàn)的幾起案子幕屹,更是在濱河造成了極大的恐慌,老刑警劉巖级遭,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件望拖,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡挫鸽,警方通過查閱死者的電腦和手機(jī)说敏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丢郊,“玉大人盔沫,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵叼屠,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我谴忧,道長(zhǎng),這世上最難降的妖魔是什么角虫? 我笑而不...
    開封第一講書人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任沾谓,我火速辦了婚禮,結(jié)果婚禮上上遥,老公的妹妹穿的比我還像新娘搏屑。我一直安慰自己争涌,他們只是感情好粉楚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著亮垫,像睡著了一般模软。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上饮潦,一...
    開封第一講書人閱讀 51,165評(píng)論 1 299
  • 那天燃异,我揣著相機(jī)與錄音,去河邊找鬼继蜡。 笑死回俐,一個(gè)胖子當(dāng)著我的面吹牛逛腿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仅颇,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼单默,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了忘瓦?” 一聲冷哼從身側(cè)響起搁廓,我...
    開封第一講書人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耕皮,沒想到半個(gè)月后境蜕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡凌停,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年粱年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苦锨。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逼泣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出舟舒,到底是詐尸還是另有隱情拉庶,我是刑警寧澤,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布秃励,位于F島的核電站氏仗,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏夺鲜。R本人自食惡果不足惜皆尔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望币励。 院中可真熱鬧慷蠕,春花似錦、人聲如沸食呻。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仅胞。三九已至每辟,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間干旧,已是汗流浹背渠欺。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留椎眯,地道東北人挠将。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓胳岂,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親舔稀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子旦万,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容