用koa寫項目後臺遇到的bug及解決
-
import,exports使用ES6規範時,項目運行會報錯:
原因:是因爲目前 NodeJs 只支持部分 ES6 的語法,有些 ES6 的語法還不支持,而 import 語法就是其中之一
解決: 改爲CommonJs 的語法格式,諸如:
const Koa = require('koa')
module.exports = app
-
Error: get
/login
:middleware
must be a function, notundefined
分析:我的邏輯是將路由記錄寫在router裏,然後按API分成若干js文件,真正完成業務邏輯的部分放在了controllers層,對應某api_controller,bug中的/login是我的一個處理登錄邏輯的中間件
在app.js中 :我將路由註冊:
// routes 註冊路由 app.use(user.routes(), user.allowedMethods())
routes–>user.js中:
const router = require('koa-router')() const user_controller = require('../controllers/user_controller') // koa-router提供一種router.prefix方法,此方法對於某一個router來說,是一個全局配置,此router的所有路徑都會自動被添加該前綴。 router.prefix('/user') router.get('/login', user_controller.login) module.exports = router
controllers–>user_controller中:
const login = async(ctx,next) => { const req = ctx.request.body ctx.body = 'this is a users/login response' } module.exports = { login }
最初沒有寫
module.exports = {
時就報了這個error!!!
login
}原因及解決:的原因是routes裏定義的API
router.get('/login', user_controller.login)
和controllers裏的exports沒有對應上 !!! -
port 3000 is already in us
e的一種可能原因:問題在於重複起調同一個端口,有的人的寫法是在app.js中寫
app.listen(...)
,有的人會獨立建立一個js來描述端口的事宜,如:www.js:
#!/usr/bin/env node /** * Module dependencies. */ var app = require('../app') var debug = require('debug')('demo:server') var http = require('http') // var coinfig = require('../config') /** * Get port from environment and store in Express. */ // 在端口3000監聽: var port = normalizePort(process.env.PORT || '3000') // app.set('port', port); /** * Create HTTP server. */ var server = http.createServer(app.callback()) /** * Listen on provided port, on all network interfaces. */ server.listen(port) server.on('error', onError) server.on('listening', onListening) /** * Normalize a port into a number, string, or false. */ function normalizePort (val) { var port = parseInt(val, 10) if (isNaN(port)) { // named pipe return val } if (port >= 0) { // port number return port } return false } /** * Event listener for HTTP server "error" event. */ function onError (error) { if (error.syscall !== 'listen') { throw error } var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port // handle specific listen errors with friendly messages switch (error.code) { case 'EACCES': console.error(bind + ' requires elevated privileges') process.exit(1) // eslint-disable-next-line no-unreachable break case 'EADDRINUSE': console.error(bind + ' is already in use') process.exit(1) // eslint-disable-next-line no-unreachable break default: throw error } } /** * Event listener for HTTP server "listening" event. */ function onListening () { var addr = server.address() var bind = typeof addr === 'string' ? 'pipe ' + addr : 'port ' + addr.port debug('Listening on ' + bind) }
以上兩種任寫一種即可,多些即會報這個錯,表示端口已經被佔用
-
連接數據庫時,報了這個錯
erroe no.2003 cant connect to mysql server on localhost
原因是MySQL服務已經關閉
解決:右鍵啓動服務即可
-
嘗試與vuecli2寫的前臺交互時出來一個錯誤:
vuecli服務器正常顯示 DONE Compiled successfully in 224628ms,
但是網頁控制檯顯示錯誤:Refused to load the image ‘http://localhost:8080/favicon.ico
’ because it violates the following Content Security Policy directive: “default-src ‘none’”. Note that ‘img-src’ was not explicitly set, so ‘default-src’ is used as a fallback.頁面只有Cannot GET /
最後發現是曾經把vuecli2項目打包過,打包時時要把config–>index.js中的
assetsPublicPath: '/'
改成`assetsPublicPath: ‘./’,因此現在解決這個問題就要把它統統改回來就沒有問題了
-
重啓服務器時,koa這邊的項目突然變的奇慢無比,而且訪問API時會報404:
發現是啓動時路徑寫錯了,出了點小問題,因爲要的路徑是當前路徑的父目錄的兄弟,所以它會繞彎子訪問,所以一開始訪問3000時沒有報錯只是很慢,到API就會404的原因
-
Access to XMLHttpRequest at ‘http://localhost:3000/user/login?user_name=1326&user_password=789456’ from origin ‘http://localhost:8080’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
典型跨域報的錯誤,就算在本機上,端口不同也是需要跨域的(改成統一端口就佔用端口了)
當域名、端口、協議有任意一個不一樣的時候就會存在跨域
解決如下:
npm install --save koa2-cors
var Koa = require('koa'); var cors = require('koa2-cors'); var app = new Koa(); app.use(cors({ origin: function (ctx) { if (ctx.url === '/test') { return "*"; // 允許來自所有域名請求 } return 'http://localhost:8080'; // 這樣就能只允許 http://localhost:8080 這個域名的請求了 }, exposeHeaders: ['WWW-Authenticate', 'Server-Authorization'], maxAge: 5, credentials: true, allowMethods: ['GET', 'POST', 'DELETE'], allowHeaders: ['Content-Type', 'Authorization', 'Accept'], }))
-
曾經安裝了MySQL,那我還需要使用npm install -g mysql嗎?
答案是需要的,mysql數據庫是存放數據的,裏面有庫和表;而npm安裝的是MySQL的驅動程序,你的應用通過這個驅動程序連接並操作mysql中的庫和表。
-
連接好表後,需要使用Sequelize進行對數據庫表的映射,很多博客會教你如何寫,其實它是可以自動生成的:下圖是數據庫的表,我們需要給他們建立映射。
需要全局安裝sequelize-auto:sequelize-auto
使sequelize-auto命令操作數據庫(MySQL):npm install -g tedious
根據sequelize-auto自動生成model且生成指定的表對應的js:(以studio表爲例)
sequelize-auto -h localhost -d ttms -u root -x 123456 -p 3306 -t studio
其中,
-h是你的數據庫IP地址
-d是數據庫庫名
-x是數據庫密碼
-p 是數據庫端口號
-t是需要映射的表名
但是,需要注意的是由於是自動生成的,有的地方還有問題,(例如自增長在映射里老是不會自動生成)使用時需要敏感一些,如有問題就手動寫一些語句輔助
xxx POST /user/register 500 368ms - ....cannot be an array or an object
這個錯基本都是少些了異步操作,需要補上一些await
才行
給幾個例子:
在controllers–>user_controller.js裏使用:
// 註冊新用戶
const register = async(ctx,next) => {
ctx.status = 200 // post 默認是404
const req = ctx.request.body
const user_name = req.user_name
const phonenumber = req.phonenumber
var password =await encrypt(req.user_password) // 此處若不寫await得到的將是一個promise對象
console.log(password)
// ctx.body = data
let user = userModel.build({
user_name,
phonenumber,
user_password: password
});
user = await user.save();
}
一開始沒寫var password =await encrypt(req.user_password)
裏的await於是報了這個錯,我當時硬把結果String保存說可以的,但是打印出來是 promise:{…}然後就意識到應該這樣操作。
// 獲取打印票面信息
const getTicketByUserAndPlan = async(ctx,next) => {
const user_name = ctx.query.user_name
const plan_id = ctx.query.plan_id
const userInfo = await getbUserId(userModel,user_name) // 注意await
const user_id = userInfo[0].dataValues.user_id
ctx.body = await ticketModel.findAll({ // 注意await
where:{ user_id, plan_id},
attributes: [ 'user_id', 'studio_name', 'startTime', 'endTime', 'seat_row', 'seat_col' ]
})
}
上面代碼兩處不寫await也會報一樣的500的信息
- POST時出現404的可能性:
- 路徑寫錯了
- ctx.status有問題
- 去看看路由那裏是不是寫成了GET
- 當npm了很多次還是報錯Cannot find module …時,看看你npm的路徑,可能路徑就有問題
我之後會把這篇博客拆開,便於尋找對應的錯誤,這個就是做個總結了