1

背景

我正在使用 koa2 和一些中间件来构建一个基本的 api 框架。但是当我在路由器中使用“ctx.body”发送响应时,客户端总是收到“未找到”

我的代码

./app.js

const Koa = require('koa');
const app = new Koa();
const config = require('./config');

//Middlewares
const loggerAsync = require('./middleware/logger-async')
const bodyParser = require('koa-bodyparser')
const jsonp = require('koa-jsonp')
app.use(loggerAsync())
app.use(bodyParser())
app.use(jsonp());

//Router
const gateway = require('./router/gateway')
app.use(gateway.routes(), gateway.allowedMethods());

app.use(async(ctx, next) => {
    await next();
    ctx.response.body = {
        success: false,
        code: config.code_system,
        message: 'wrong path'
    }
});

app.listen(3000);

./router/gateway.js

/**
 * Created by Administrator on 2017/4/11.
 */
const Router = require('koa-router');
const gateway = new Router();
const df = require('../db/data-fetcher');
const config = require('../config');
const moment = require('moment');
const log4js = require('log4js');
// log4js.configure({
//     appenders: { cheese: { type: 'file', filename: 'cheese.log' } },
//     categories: { default: { appenders: ['cheese'], level: 'error' } }
// });
const logger = log4js.getLogger('cheese');
logger.setLevel('ERROR');


gateway.get('/gateway', async(ctx, next) => {
    let time = ctx.query.time;
    if (!time) {
        ctx.body = {
            success: false,
            code: config.code_system,
            message: 'Please input running times'
        }
    } else {
        try {
            let r = await df(`insert into gateway (g_time, g_result, g_date) values (${time}, '',now())`);
            return ctx.body = {
                success: true,
                code: config.code_success
            }
        } catch (error) {
            logger.error(error.message);
        }
    }
});

module.exports = gateway;

然后是一个数据库包装器(mysql)

./db/async-db.js

const mysql = require('mysql');
const config = require('../config');

const pool = mysql.createPool({
    host: config.database.HOST,
    user: config.database.USERNAME,
    password: config.database.PASSWORD,
    database: config.database.DATABASE
})

let query = (sql, values) => {
    return new Promise((resolve, reject) => {
        pool.getConnection(function (err, connection) {
            if (err) {
                reject(err)
            } else {
                connection.query(sql, values, (err, rows) => {

                    if (err) {
                        reject(err)
                    } else {
                        resolve(rows)
                    }
                    connection.release()
                })
            }
        })
    })
}

module.exports = query

./db/data-fetcher.js

const query = require('./async-db')
async function performQuery(sql) {
    let dataList = await query(sql)
    return dataList
}

module.exports = performQuery;

我的跑步结果

当我在端口 3000 上启动服务器然后通过http://localhost:3000/gateway?time=5访问时,它总是返回“未找到”。但正如我所见,我已经使用过

return ctx.body = {
                success: true,
                code: config.code_success
            }

发送响应。调试了一下,发现数据库处理做得不错,新数据插入也不错。

当我删除该数据库插入行时,它运行良好并返回成功信息。

let r = await df(`insert into gateway (g_time, g_result, g_date) values (${time}, '',now())`);

有什么问题吗?

非常感谢!

更新 2017/04/27

现在我发现了问题。这是由于我的自定义中间件

const loggerAsync = require('./middleware/logger-async')

代码如下 -

function log( ctx ) {
    console.log( ctx.method, ctx.header.host + ctx.url )
}

module.exports = function () {

    return function ( ctx, next ) {

        return new Promise( ( resolve, reject ) => {

            // 执行中间件的操作
            log( ctx )

            resolve()

            return next()

        }).catch(( err ) => {

            return next()
        })
    }

}

我将其更改为异步/等待方式,然后一切正常。

谁能告诉我这个中间件有什么问题?

4

2 回答 2

0

我想,你的问题是./db/data-fetcher.js功能。当你打电话时

let r = await df(`insert ....`)

你的df- 函数应该返回一个承诺。

所以尝试./db/data-fetcher.js像这样重写你的(未经测试):

const query = require('./async-db')

function performQuery(sql) {
    return new Promise((resolve, reject) => {
        query(sql).then(
            result => {
                resolve(result)
            }
        )
    }
}

module.exports = performQuery;

希望有帮助。

于 2017-04-18T20:08:46.313 回答
0

正确的中间件:

function log( ctx ) {
    console.log( ctx.method, ctx.header.host + ctx.url )
}

module.exports = function () {
    return function ( ctx, next ) {
        log( ctx );
        return next()
    }
}

原因:resolve涉及时;承诺链完成;响应已发送给客户端。虽然中间件仍然会涉及,但响应已经消失了!

试着理解It seems that if you want to use a common function as middleware, you have to return the next function

nodejs(koa):发送后无法设置标头

于 2017-08-22T11:53:30.000 回答