【发布时间】:2017-03-01 21:45:34
【问题描述】:
构建我的第一个 HAPI api 后端,但遇到了一些奇怪的事情。当我第一次到达端点时(GET /api/item/{name},我可以在控制台中看到处理程序函数正在运行(mongo 查询),然后发送回复(有一个响应插件-记录这些)。太好了。如果我用不同的参数再次访问端点,我会看到第一次调用的响应立即发出,然后处理函数被命中。事实上,客户端得到的结果是一样的从第一次调用开始的响应。
我什至不确定在这里发布什么最有帮助。
这里是大部分入口点 js(缺少环境和 winston 的配置):
const Hapi = require('hapi');
server = new Hapi.Server();
var mongo_connect = 'mongodb://' + options.mongo_creds + options.mongo_host + ':' + options.mongo_port + '/' + options.mongo_db;
const dbOpts = {
url: mongo_connect,
settings: {
poolSize: options.mongo_pool
},
decorate: true
};
server.connection({ port: options.server_port });
var routes = require('./routes');
if (options.env === "dev") {
server.on('response', function (request) {
winston.log('verbose', `[launch_api] ${request.info.remoteAddress}: ${request.method.toUpperCase()} ${request.url.path} --> ${request.response.statusCode}`);
});
}
server.register({
register: require('hapi-mongodb'),
options: dbOpts
}, function(err) {
if (err) {
winston.log('error', "[launch_api] Unable to register db pool");
throw err;
}
server.route(routes);
server.start(function(err) {
if (err) {
throw err;
}
winston.log('info', `[launch_api] Server running at: ${server.info.port}`);
});
});
路由在路由文件夹中的 index.js 中被拉到一起,但其中的每个文件看起来像:
'use strict';
var controller = require('../controllers/item-controller')
// Routes for Item
module.exports = [
{
method: 'POST',
path: '/api/item',
config: controller.create
},
{
method: 'GET',
path: '/api/items',
config: controller.fetchAll
},
{
method: 'GET',
path: '/api/item/{name}',
config: controller.find
}
];
所有的控制器看起来都是这样的(为了简洁起见,只显示 find 函数,因为这已经很长了)
const Boom = require('boom');
const Joi = require('joi');
const Item = require('../models/item');
module.exports = {
find: {
handler: function(request, reply) {
Item.initFromName(request.params.name).then( function(newItem) {
if (newItem == null) {
reply(Boom.notFound());
}
else {
reply(newItem);
}
}, function(err) {
reply(Boom.badImplementation());
});
}
}
}
最后,模型倾向于遵循这个,呃,模型(同样,删掉所有原型扩展,只在这条路线中保留一个类函数)
const deferred = require('deferred')()
const winston = require('winston');
const collection_name = "items";
var Item = function() {
this.name = "";
this.description = "";
};
// private
function fillFromDB(obj, record) {
obj._id = record._id;
obj.name = record.name;
obj.description = record.description;
}
// Constructor
module.exports.init = function() {
return new Item();
};
module.exports.initFromName = function(name) {
var item = new Item();
const db = server.mongo.db;
db.collection(collection_name).findOne({name: name}).then( function(opResult) {
winston.log("debug","Item.loadFromName opResult is: " + opResult);
if (opResult != undefined) {
winston.log("debug","Item.loadFromName opResult json is: " + JSON.stringify(opResult));
fillFromDB(item, opResult);
deferred.resolve(item);
}
else {
winston.log("debug","Resolving with null" );
deferred.resolve();
}
}, function(err) {
winston.log("error", "Item.loadFromName mongo error: " + err);
deferred.reject();
});
return deferred.promise;
};
因此,如果我用 curl 访问我的端点,其名称在集合中 not 存在,我会得到预期的 404。如果我然后点击一个名称,我仍然会得到 404。
这个输入:
$ curl -X GET http://192.168.99.100:3000/api/item/not_here
{"statusCode":404,"error":"Not Found"}
$ curl -X GET http://192.168.99.100:3000/api/item/here
{"statusCode":404,"error":"Not Found"}
产生此日志:
debug: Item.loadFromName opResult is: null
debug: Resolving with null
verbose: [launch_api] 192.168.99.1: GET /api/item/not_here --> 404
verbose: [launch_api] 192.168.99.1: GET /api/item/here --> 404
debug: Item.loadFromName opResult is: [object Object]
debug: Item.loadFromName opResult json is: {"_id":"58b622908ea4d1cee2f46462","name":"here","description":"this item is here"}
请注意,相反的方向也可以。如果我停止并启动节点,然后使用存在的名称命中端点,则所有后续调用都将返回相同的对象。我只是无法弄清楚这种缓存发生在哪里。
【问题讨论】:
-
总结您的问题,hapi 似乎正在缓存响应?
-
是的,我应该这么说,嗯? tl;dr :) 但是我没有做任何我能看到的启用缓存,我想我在我正在扫描的一个 catbox tuts 中看到它必须明确启用。
-
initFromName 函数中的 item 变量来自哪里?这可能会导致问题,什么是延迟库?使用回复接口时,Promise 需要正确包装。
-
啊,清理过程中编辑错误,抱歉,这是函数的第一行,将进行编辑。
-
Deferred 是直接的 npm 延迟库。不确定“需要正确包装承诺”是什么意思 - 在此处构建回复之前,应解决或拒绝所有承诺。即回复只在控制器中完成,任何承诺都在模型或以下。
标签: javascript node.js hapijs