请求处理程序无法使用 Vision 插件呈现视图

Request handler unable to render view with Vision plugin

我正在开发 HapiJS api 并且我已经定义了一个插件来注册 Vision 插件并配置渲染引擎 (ejs)。但是当我尝试通过呈现视图来响应请求时,我得到了错误

AssertionError [ERR_ASSERTION]: Missing views manager

如果我在插件外部的某处注册了 Vision 插件及其配置,测试就会通过,但我的期望是我应该能够将此逻辑封装在插件中。

// plugin
const ejs = require('ejs');
const Vision = require('vision');

module.exports = {
    name: 'views',
    version: '0.0.1',
    register: async (server, { path }) => {
        await server.register(Vision);
        server.views({
            engines: { ejs },
            path,
        });
    },
};

处理程序代码是

// api
server.route({
  path: '/korin/songs',
  method: 'GET',
  handler: async (request, h) => {
    try {
      const acceptType = getMediaType(request.headers.accept);
      const data = await server.methods.getTopTracks({
        getTopTracks,
        lastfmApi,
      });
      if (acceptType === 'text/html') {
        return h.view('index'); // <-- this errors
      }
      return data;
    } catch (error) {
      console.warn(error);
    }
  },
});

错误是由失败的测试生成的,

suite('render content', () => {
    test.only(`given text/html page should respond with header and footer`, async () => {
        const { server } = await setup();
        const { payload } = await server.inject({
            method: 'GET',
            url: '/korin/songs',
            headers: {
                accept: 'text/html',
            },
        });

        expect(payload).to.contain(`<header>`);
        expect(payload).to.contain(`<footer>`);
    });
});
// test setup
const setup = async options => {
    const server = new Hapi.Server();

    // truncated for brevity
    await server.register({
        plugin: require('../../server/api'),
        options: {
            ...defaults,
            ...options,
        },
    });

    await server.register({
        plugin: require('../../server/views'),
        options: { path: path.join(__dirname, '../views/templates') },
    });

    return {
        server
    };
};

有什么我想念的吗?我试过 运行 和 console.log,代码似乎 运行 的顺序是正确的,但还是失败了。

关于这个有一个old thread on GitHub。 TL;DR:注册时传递给插件的 server 引用 与 "root" server 略有不同。关于 realms 的一些差异,显然仍然是一个问题。

确实:在插件中,server.getViewsManager()(由vision装饰)在注册visionserver.views后会显示一些东西,而在你的路由中调用相同(因此,在插件注册后)将显示 null。 "references".

这么多

我刚刚尝试了一个与你相似的结构,得到了同样的错误,这个线程向我指出了一个解决方法:在注册你的 views 插件时,只需传递对 "real" 的引用server 在选项中。

// plugin
const ejs = require('ejs');
const Vision = require('vision');

module.exports = {
    name: 'views',
    version: '0.0.1',
    register: async (server, { path, realServer }) => { // <= added option
        await realServer.register(Vision); // <= replaced server w/ realServer
        realServer.views({ // <= replaced server w/ realServer
            engines: { ejs },
            path,
        });
    },
};
// test setup
// ...
    const server = new Hapi.Server();
    // ...
    await server.register({
        plugin: require('../../server/views'),
        options: {
            path: path.join(__dirname, '../views/templates'),
            realServer: server // <= added option
        }
    });

而且,显然,在您注册此插件的任何地方都有相同的选项。