微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在没有 http 服务器的情况下在内部使用 koa 应用回调?

如何解决如何在没有 http 服务器的情况下在内部使用 koa 应用回调?

A 有一个基于 koa 的 js 应用程序并致力于服务器端渲染。在应用程序的其余部分中,我正在从运行 SSR 的同一台服务器加载一些脚本。虽然加载可以通过标准的 HTTP 请求,但它会不必要地慢。所以我想简单地调用 koa 提供的 app.callback() 将请求解析为请求文件的字符串。对于 SSR,我使用 jsdom,它加载文件并作为浏览器处理它们。

问题是我无法得到结果,resp。 “服务器响应”的主体。我试图模拟服务器请求和服务器响应,然后只是读取套接字。我不确定这是否是最好的方法,但它似乎可行。但是,当我运行该应用程序时,我只得到两个块 - 用于大型前端文件的字符串缓冲区。第一个块是标题。其次是代码的一部分,但只有 64kB。我无法获得下一块。似乎模拟的可写流停止了。也许它被塞住了,但我不确定为什么以及是否完全。

如果我尝试加载小于 64kB 的脚本,请求将被正确解析并且流已完成。

const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const { Writable } = require("stream");
const http = require("http");
const fetch = async (url,options) => {
        const response = [];
        let finishedReolve;
        const finished = new Promise(resolve => (finishedReolve = resolve));
        const socket = new Writable({
                write: (data,encoding,cb) => {
                        console.log("write",data);
                        // outputs 2 times - 1. headers,2. 64kB part of requested code
                        response.push(data);
                        cb();
                        return true;
                },destroy(err,cb) {
                        // Never gets called
                        console.log("destroy",err);
                        cb();
                        finishedReolve();
                },final(cb) {
                        // Never gets called
                        console.log("final");
                        cb();
                        finishedReolve();
                },});
        const req = new http.IncomingMessage(socket);
        req.method = "GET";
        const parsedURL = new URL(url);
        req.url = parsedURL.pathname;
        const res = new http.ServerResponse(req);
        res.assignSocket(req.socket);
        res.on("prefinish",() => {
                // Never gets called
                finishedReolve();
        });
        await this.callback()(req,res);
        await finished;
        return response[0];
};
class CustomresourceLoader extends jsdom.ResourceLoader {
        fetch(url,options) {
                return fetch(url,options);
        }
}
const dom = await JSDOM.fromFile(index_html_path,{
        url: domain + ctx.req.url,runScripts: "dangerously",resources: new CustomresourceLoader(),});

流有什么问题?有没有其他方法可以使用 app.callback()获取 koa 应用程序的输出

解决方法

问题是,可读流正在发送 64kB 的块,但我的可写流将 highWaterMark 设置为默认 16kB。这(可能)导致可读流在写入更多可写可以处理的数据后等待耗尽,这是在第一个 64kB 块之后。

解决方案是将 highWaterMark 设置为大于可读流的值,因此例如

highWaterMark: 1024 * 64 * 2,

所以套接字看起来像这样:

const socket = new Writable({
        highWaterMark: 1024 * 64 * 2,write: (data,encoding,cb) => {
                response.push(data);
                cb();
                return true;
        },destroy(err,cb) {
                console.log("destroy",err);
                cb();
                finishedReolve();
        },final(cb) {
                console.log("final");
                cb();
                finishedReolve();
        },});

还要结束,我需要听那个奇怪的事件 prefinish

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。