新聞中心
一、Nodejs Server的基礎(chǔ)知識(shí)

專(zhuān)業(yè)領(lǐng)域包括成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、購(gòu)物商城網(wǎng)站建設(shè)、微信營(yíng)銷(xiāo)、系統(tǒng)平臺(tái)開(kāi)發(fā), 與其他網(wǎng)站設(shè)計(jì)及系統(tǒng)開(kāi)發(fā)公司不同,創(chuàng)新互聯(lián)的整合解決方案結(jié)合了幫做網(wǎng)絡(luò)品牌建設(shè)經(jīng)驗(yàn)和互聯(lián)網(wǎng)整合營(yíng)銷(xiāo)的理念,并將策略和執(zhí)行緊密結(jié)合,為客戶(hù)提供全網(wǎng)互聯(lián)網(wǎng)整合方案。
1、基礎(chǔ)的HTTP服務(wù)器
只要在本地或服務(wù)器安裝了Node環(huán)境,使用 require('http')引入http模塊,就能用http.createServer()方法創(chuàng)建一個(gè)服務(wù)器。比如我們使用VS Code新建一個(gè)app.js的文件(保存在電腦的到哪里都行),然后輸入以下代碼:
const http = require('http'); //引入內(nèi)置的http模塊
const hostname = '127.0.0.1';
const port = 3000;
const requestHandler = (req, res) => { //
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html;charset=utf-8');
res.end('Node Server創(chuàng)建成功啦');
console.log(`請(qǐng)求鏈接是:${req.url},請(qǐng)求方法是:${req.method}`)
}
const server = http.createServer(requestHandler) //使用 http.createServer() 方法創(chuàng)建服務(wù)器
server.listen(port, hostname, () => { //listen為createServer返回對(duì)象的方法,用于指定HTTP服務(wù)器監(jiān)聽(tīng)的端口號(hào)
console.log(`通過(guò)此鏈接訪(fǎng)問(wèn)服務(wù)器 http://${hostname}:${port}/`);
});
保存后,在VS Code里右鍵該文件選擇在終端中打開(kāi),然后在VS Code的終端中輸入以下代碼按Enter執(zhí)行:
node app.js
在瀏覽器里輸入http://127.0.0.1:3000/,就能訪(fǎng)問(wèn)我們創(chuàng)建好的服務(wù)器啦,頁(yè)面也會(huì)顯示Node Server創(chuàng)建成功啦,可以說(shuō)使用Nodejs創(chuàng)建一個(gè)HTTP服務(wù)器非常容易。
注意requestHandler有兩個(gè)參數(shù),req是request請(qǐng)求對(duì)象,調(diào)用request對(duì)象就可以拿到所有HTTP請(qǐng)求的信息,比如request.url獲取請(qǐng)求路徑;res是response響應(yīng)對(duì)象,調(diào)用response對(duì)象的方法,就可以把HTTP響應(yīng)返回給瀏覽器了。當(dāng)用戶(hù)每訪(fǎng)問(wèn)一次(比如刷新一下頁(yè)面)就會(huì)觸發(fā)requestHandler函數(shù),我們也能在終端看到打印的日志。
2、文件服務(wù)器
借助于fs 模塊: 可以對(duì)文件目錄進(jìn)行創(chuàng)建、刪除、查詢(xún)以及文件的讀取和寫(xiě)入以及url模塊: 可以處理與解析 URL,我們可以把服務(wù)器里的文件發(fā)送給客戶(hù)端。比如我們可以修改一下app.js的代碼為如下:
var http = require('http');
var url = require('url');
var fs = require('fs');
http.createServer( (req, res) => { //這里把上面的requestHandler給整到一起了,注意一下
const requrl = url.parse(req.url, true);
const filename = "." + requrl.pathname; //這里的.表示的是相對(duì)路徑
fs.readFile(filename, function(err, data) {
if (err) {
res.writeHead(404, {'Content-Type': 'text/html;charset=utf-8'});
return res.end("404 頁(yè)面沒(méi)有找到");
}
res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'});
res.write(data);
console.log(`請(qǐng)求鏈接是:${req.url},請(qǐng)求方法是:${req.method}`);
return res.end();
});
}).listen(3000);
然后再在終端執(zhí)行node app.js(如果你之前的node server還在執(zhí)行,你可以連續(xù)按兩次Ctrl+C來(lái)終止服務(wù)器,再來(lái)執(zhí)行node app.js)。放一個(gè)文件比如tcb.jpg到app.js的相同目錄里,在瀏覽器里輸入如下地址(也就是ip地址+文件的路徑)看看:
http://127.0.0.1:3000/tcb.jpg
本地調(diào)試時(shí),服務(wù)器和客戶(hù)端都是同一條電腦,我們使用瀏覽器打開(kāi)
http://127.0.0.1:3000/就能通過(guò)瀏覽器訪(fǎng)問(wèn)到服務(wù)器里的文件。
二、托管Nodejs Server
那云函數(shù)是否可以搭建一個(gè)Nodejs的服務(wù)器呢,結(jié)合云接入和云函數(shù),可以很輕松地托管Nodejs服務(wù)端程序。這里就要使用到serverless-http的模塊。我們可以使用serverless-http把集成請(qǐng)求轉(zhuǎn)化為 Node.js Server 能接收的 IncommingMessage,同時(shí)把返回的 ServerResponse 轉(zhuǎn)化為集成請(qǐng)求。
使用VS Code在functions文件夾里新建一個(gè)云函數(shù),比如server,和小程序云開(kāi)發(fā)的云函數(shù)一樣新建3個(gè)文件,以及assets文件夾,里面存放我們要返回的HTML文件、圖片等各種靜態(tài)資源,結(jié)構(gòu)如下:
├── server //server云函數(shù)目錄
│ └── assets
│ └── index.html
│ └── demo.jpg
│ └── index.js
│ └── config.json
│ └── package.json
并在package.json里添加serverless-http依賴(lài),
"dependencies": {
"wx-server-sdk": "latest",
"serverless-http": "latest"
}
然后再在index.js里輸入以下代碼,我們把之前Nodejs Server里的代碼Copy過(guò)來(lái),注意與普通云函數(shù)和集成請(qǐng)求寫(xiě)法的不同。
const cloud = require('wx-server-sdk')
const url = require('url')
const fs = require('fs')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
const serverless = require('serverless-http');
const requestHandler = (req, res) => { //
const requrl = url.parse(req.url, true);
const filename = "." + requrl.pathname; //這里的.表示的是相對(duì)路徑
fs.readFile(filename, function(err, data) {
if (err) {
res.writeHead(404, {'Content-Type': 'text/html;charset=utf-8'});
return res.end("404 頁(yè)面沒(méi)有找到");
}
res.writeHead(200, {'Content-Type': 'text/html;charset=utf-8'});
res.write(data);
console.log(`請(qǐng)求鏈接是:${req.url},請(qǐng)求方法是:${req.method}`);
return res.end();
});
}
exports.main = serverless(requestHandler);
終端進(jìn)入云函數(shù)目錄server文件夾,使用npm install安裝依賴(lài),然后再回退到項(xiàng)目根目錄使用CLoudbase Cli命令將云函數(shù)部署到云端并創(chuàng)建server云函數(shù)云接入的路由,再用瀏覽器或cURL命令訪(fǎng)問(wèn)云接入鏈接:
cloudbase functions:deploy server
cloudbase service:create -p /server -f server
這樣我們就能通過(guò)云接入的鏈接來(lái)訪(fǎng)問(wèn)托管的服務(wù)器里面的資源了,只要是云函數(shù)目錄里面的資源就都能訪(fǎng)問(wèn),云函數(shù)就”化身“成了一個(gè)服務(wù)器了。比較一下集成請(qǐng)求返回html與托管Nodejs Server的不同。
https://xly-xrlur.service.tcloudbase.com/server/assets/index.html
三、托管 Koa.js
Koa和Express都是基于Nodejs平臺(tái)的web應(yīng)用開(kāi)發(fā)框架,可以對(duì)HTTP Request對(duì)象和HTTP Response對(duì)象進(jìn)行封裝處理,以及生命周期的維護(hù),路由、視圖的處理等等。云接入和云函數(shù)可以托管Nodejs Server,它也支持托管Koa和Express,下面就以Koa為例。
1、托管Koa
我們還是以server云函數(shù)為例,首先在server云函數(shù)的package.json里添加koa依賴(lài),然后將index.js改為如下代碼,仍然讀取云函數(shù)目錄下的assets文件里的index.html文件:
const cloud = require('wx-server-sdk')
const fs = require('fs')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
const serverless = require('serverless-http');
const Koa = require('koa');
const app = new Koa();
app.use(async ctx => {//ctx是由koa傳入的封裝了request和response的變量,通過(guò)它可以訪(fǎng)問(wèn)request和response
ctx.response.type = 'text/html;charset=utf-8'; //ctx.response就是Node的response對(duì)象
ctx.response.body = fs.createReadStream('./assets/index.html');
})
exports.main = serverless(app);
進(jìn)入云函數(shù)目錄下載云函數(shù)的依賴(lài)之后,回退到項(xiàng)目根目錄部署上傳server云函數(shù),再使用瀏覽器打開(kāi)server云函數(shù)的云接入地址就能看到解析好的index.html了。
Koa 的Context 上下文將 node 的 request 和 response 對(duì)象封裝到單個(gè)對(duì)象中,為編寫(xiě) Web 應(yīng)用程序和 API 提供了許多有用的方法。為方便起見(jiàn)許多上下文的訪(fǎng)問(wèn)器和方法直接委托給它們的 ctx.request或 ctx.response。ctx.response就是Node的response對(duì)象,ctx.request就是Node的request對(duì)象。
2、Koa原生路由
使用Koa也能讓云函數(shù)+云接入作為文件服務(wù)器,把云函數(shù)目錄下的文件都返回給瀏覽器,我們將server云函數(shù)的代碼修改為如下,這個(gè)功能和前面的托管Nodejs Server類(lèi)似:
const cloud = require('wx-server-sdk')
const fs = require('fs')
const url = require('url')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
const serverless = require('serverless-http');
const Koa = require('koa');
const app = new Koa();
app.use( async ( ctx ) => {
const requrl = url.parse(ctx.request.url, true);
const filename = "." + requrl.pathname;
ctx.response.type = 'text/html;charset=utf-8';
ctx.body =fs.createReadStream(filename)
})
exports.main = serverless(app);
將Server云函數(shù)部署上傳,和前面一樣我們可以在瀏覽器里輸入以下地址來(lái)訪(fǎng)問(wèn)server云函數(shù)目錄里的assets文件夾里的index.html頁(yè)面:
https://xly-xrlur.service.tcloudbase.com/server/assets/index.html
Koa原生路由通過(guò)解析request IncomingMessage 的 url 屬性, 利用 if...else 來(lái)判斷路徑返回不同的結(jié)果,但是如果路由過(guò)多, if...else 的分支也會(huì)越龐大, 不利于代碼的維護(hù),具體的案例這里就不多寫(xiě)了,下面直接用Koa-router解決方案。
四、Koa router中間件
盡管我們可以依靠ctx.request.url這種比較原生的方式來(lái)手動(dòng)處理路由,但是這會(huì)寫(xiě)很多處理代碼,這時(shí)候就需要對(duì)應(yīng)的路由中間件對(duì)路由進(jìn)行控制,這里推薦使用Koa-router,以及推薦使用koa-bodyparser中間件。對(duì)于POST請(qǐng)求的處理,koa-bodyparser可以把ctx的formData數(shù)據(jù)解析到ctx.request.body中。
1、使用Koa router中間件
我們?nèi)匀灰詓erver云函數(shù)為例,在package.json添加如下依賴(lài),并進(jìn)入server云函數(shù)目錄下載這些依賴(lài):
"dependencies": {
"wx-server-sdk": "latest",
"serverless-http": "latest",
"koa":"latest",
"koa-bodyparser":"latest",
"koa-router":"latest"
}
然后將server云函數(shù)修改為如下代碼,然后部署上傳server云函數(shù),然后訪(fǎng)問(wèn)云接入的地址,注意打開(kāi)的頁(yè)面里的首頁(yè)和關(guān)于我們是可以點(diǎn)擊的,會(huì)跳轉(zhuǎn)到koa-router指定的路由,并返回相應(yīng)的內(nèi)容:
const fs = require('fs')
const cloud = require('wx-server-sdk')
cloud.init({
env: cloud.DYNAMIC_CURRENT_ENV
})
const serverless = require('serverless-http');
const Koa = require('koa');
const bodyParser = require('koa-bodyparser')
const app = new Koa();
const Router = require('koa-router')
const router = new Router()
app.use(bodyParser())
router.get('/',async (ctx) => {
//注意這里的路徑哈,server為云接入的路由,在前面我們把server云函數(shù)的路由設(shè)置為server
let html = `
ctx.body = html
})
router.get('/home',async (ctx) => {
ctx.response.type = 'text/html;charset=utf-8';
ctx.response.body = fs.createReadStream('./assets/index.html');
})
router.get('/about', async ( ctx )=>{
ctx.body = '歡迎您的關(guān)注,網(wǎng)頁(yè)還在建設(shè)當(dāng)中'
})
app.use(router.routes()) // 添加路由中間件
app.use(router.allowedMethods()) // 對(duì)請(qǐng)求進(jìn)行一些限制處理
exports.main = serverless(app);
當(dāng)我們打開(kāi)云接入地址/home時(shí),返回的是云函數(shù)目錄下的assets文件夾里的index.html頁(yè)面,而事實(shí)上云函數(shù)目錄并沒(méi)有home這個(gè)文件夾,按照之前的方式打開(kāi)云接入地址/assets/index.html也打不開(kāi)了,這個(gè)就是路由重定向。
這個(gè)案例僅僅只是使用了GET方法來(lái)進(jìn)行注冊(cè)路由,我們還可以使用POST、DELETE、PUT、DEL、ALL等方法。而koa-router路由也還支持變量等,這里就不展開(kāi)啦。
2、路由中間件與云開(kāi)發(fā)
有了路由中間件,我們就能把最常見(jiàn)的GET、POST請(qǐng)求都集成在一個(gè)云函數(shù)里,比如數(shù)據(jù)庫(kù)、云存儲(chǔ)的增刪改查,從而將該云函數(shù)作為API服務(wù)器,向前端返回所需數(shù)據(jù)和執(zhí)行指定的操作。在小程序端我們可以使用wx.request()接口發(fā)起HTTPS網(wǎng)絡(luò)請(qǐng)求(值得注意的是小程序端需要將云接入的域名添加到小程序里的域名白名單內(nèi)),在Web端則可以通過(guò)axios。
獲取數(shù)據(jù)庫(kù)里的數(shù)據(jù)
比如我們用Koa router可以添加一個(gè)路由getData,用來(lái)返回云數(shù)據(jù)庫(kù)查詢(xún)到的數(shù)據(jù)結(jié)果:
router.get('/getData',async (ctx) => {
ctx.body = await db.collection('china').where({
gdp: _.gt(3000)
})
.field({
_id:false,
city: true,
province: true,
gdp:true
})
.orderBy('gdp', 'desc')
.skip(0)
.limit(10)
.get()
})
在小程序端獲取返回?cái)?shù)據(jù):
wx.request({
url: 'https://xly-xrlur.service.tcloudbase.com/server/getData',
success (res) {
console.log(res.data.data)
}
})
在web端獲取返回?cái)?shù)據(jù):
const url ="https://xly-xrlur.service.tcloudbase.com/server/getData"
axios.get(url).then(res => {
console.log(res.data)
}).catch(err => {
console.log(err)
})
往數(shù)據(jù)庫(kù)里添加數(shù)據(jù)庫(kù)
我們還可以使用Koa router提供POST接口,對(duì)前端傳來(lái)的參數(shù)、數(shù)據(jù)進(jìn)行處理,比如我們可以往數(shù)據(jù)庫(kù)里添加數(shù)據(jù),只需要注意Koa是如何獲取參數(shù)和數(shù)據(jù)的即可。
router.post('/addData',async (ctx) => {
const {userInfo} = await ctx.request.body
const addUser = await db.collection('china').add({
data:userInfo
})
ctx.body = addUser
})
小程序端發(fā)起POST請(qǐng)求的代碼如下:
wx.request({
url: 'https://xly-xrlur.service.tcloudbase.com/server/addData',
method:"POST",
data:{
userInfo:{
Name: '騰訊云云開(kāi)發(fā)',
enName: 'CloudBase'
}
},
success (res) {
console.log(res)
}
})
在web端發(fā)起POST請(qǐng)求的代碼如下:
async function addData(){
axios.post('https://xly-xrlur.service.tcloudbase.com/server/addData', {
userInfo:{
Name: '騰訊云云開(kāi)發(fā)',
enName: 'CloudBase'
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
我們還可以在小程序端或Web端調(diào)用一下server云函數(shù),看看返回的數(shù)據(jù)對(duì)象和以往的有什么不同?大致了解一下后臺(tái)函數(shù)與HTTP函數(shù)的不同。
分享文章:創(chuàng)新互聯(lián)小程序云教程:云開(kāi)發(fā)托管NodejsServer
標(biāo)題網(wǎng)址:http://www.dlmjj.cn/article/cdohope.html


咨詢(xún)
建站咨詢(xún)
