原生nodejs,res.end()无法输出到页面。

1.问题:
console.log(html),控制台输出成功,但res.end(html)无法渲染页面。

2.代码

var http = require("http");
var path = require("path");
var url = require("url");
var fs = require("fs");
var ejs = require("ejs");

var server = http.createServer(function (req, res) {
    if (req.url == "/favicon.ico") {
        return;
    }
    var pathname = url.parse(req.url).pathname;
    var fileUrl = path.normalize("./public/" + pathname);
    var extname = path.extname(pathname);

    fs.readFile(fileUrl, function (err, fileData) {
        getMime(extname, function (mime) {
            res.writeHead(200, { "context-type": mime });
            res.end(fileData);
        })
    });



    if (pathname == "/") {
        var _thisUrl = "./public"
        var fileArry = [];//存储各个文件data的一些数据
        var a = {}
        var data = {};//存储file(是否事文件,1是,0不是);fileName:文件(夹)名;url:文件实际地址
        fs.readdir(_thisUrl, function (err, files) {
            var length = files.length;
            (function iterator(i) {
                var show = 0;
                if (i >= files.length) {
                    data = { "fa": fileArry, "length": length };

                    fs.readFile("./views/index.ejs", function (err, fileData) {

                        var template = fileData.toString();
                        var html = ejs.render(template, data);
                        console.log(html);
                        res.end(html);
                    });
                    return;
                }
                fs.stat(_thisUrl + "/" + files[i], function (err, stats) {
                    if (stats.isDirectory()) {
                        a = { "file": 0, "fileName": files[i], "url": _thisUrl + "/" + files[i] }
                    }
                    else {

                        if (path.extname("/" + files[i]).toLocaleLowerCase() == ".jpg") {
                            show = 1;
                        }
                        a = { "file": 1, "fileName": files[i], "url": _thisUrl + "/" + files[i], "show": show }
                    }
                    fileArry.push(a);
                    //console.log(fileArry);
                    iterator(i + 1);
                })
            })(0);

        });

    };



});

server.listen(3000, "127.0.0.1");

function getMime(extname, fn) {
    fs.readFile("./public/mime.json", function (err, data) {
        var mimeList = JSON.parse(data);
        var mime = mimeList[extname];
        fn(mime);
    })
}

3.控制台截图
图片描述

我是小白,请解释的稍微浅显些,谢谢各位大神。
PS:我后来consol.log(res)发现,自执行函数的res和外部的res不一样,自执行函数内部的res好像少了很多,如图
图片描述

阅读 7.7k
4 个回答
if (extname) {
        return fs.readFile(fileUrl, function (err, fileData) {
            if (err) {
                res.writeHead(404, 'not found');
                return res.end();
            }
            getMime(extname, function (mime) {
                if (!mime) {
                    res.writeHead(404, 'not found');
                    return res.end();
                }
                res.writeHead(200, { "context-type": mime });
                res.end(fileData);
            })
        });
    }

应该是之前的这块在你输出html之前已经返回了,前面要做充分的判断。
还有就是这些读文件的操作为什么不在应用启动的时候直接读取后缓存,不要放在linstener函数内做,这样每个请求过来之后都要进行文件读取操作,性能大大降低了

后面的那个循环读取文件的逻辑也不对,因为是异步操作,在render的时候并不能保证fileArry中已经有所有的文件信息了

因为读文件是异步的,等你读完文件的时候请求已经处理完了

fs.readFile(fileUrl, function (err, fileData) {
        getMime(extname, function (mime) {
            res.writeHead(200, { "context-type": mime });
            res.end(fileData);  ```//你这里 end 直接结束了响应导致后面的数据没传吧```
        })
    });

可以改成下面这种方式试下:
var rs = fs.createReadStream(__dirname + '/test.txt')
rs.on('data', function (data) {
console.log(data.toString());
});
rs.on('end', function () {
console.log('读取文件结束')
});

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题