首页 > 解决方案 > 节点js中的get-request参数(不带express)

问题描述

我正在用原生节点 js 和 javascript、html、css 写博客。我正在尝试从 main.html 页面向服务器发送一个获取请求,以便不显示所有帖子,而只显示某个规则的帖子。我按照以下方式进行操作(请参见下面的代码)。但是get查询不起作用。当我单击 main.html 页面上的该链接时,没有任何反应,当我更新页面时, rubric: undefined 输出到控制台。我究竟做错了什么?

main.html(客户端):

<body>
    <a class="rub_link" id="programming" href="#">Programming</a>
    ...
    <!-- Output of posts to html -->
    <div class="posts" id="posts">
        <div class="container">
            <div class="posts_inner">         
                {card_data}
            </div>
        </div>
    </div>
    ...
    <script>
        document.querySelector('#programming').addEventListener('click', onRenderProgrammingPosts)

        function onRenderProgrammingPosts(e) {
            e.preventDefault();

            let request = new XMLHttpRequest();
            let body = "rubric=programming";
            request.open("GET", "/main?" + body, true);
        
            request.onload = function() {
                if (request.status != 200) {
                    alert(`Error ${request.status}: ${request.statusText}`);
                } else {
                    alert(`Done, received ${request.response} from the server`);
                }
            };

            request.send();
        }
    </script>
</body>

index.js(服务器):

const server = http.createServer((req, res) => {

    let filePath = path.join(__dirname, 'public', req.url === '/' ? 'login.html' : req.url)
    const ext = path.extname(filePath)
    let contentType = 'text/html'

    switch (ext) {
        case '.css':
            contentType = 'text/css'
            break
        case '.js':
            contentType = 'text/javascript'
            break
        default:
            contentType = 'text/html'
    }

    if (!ext) {
        filePath += '.html'
    }

    fs.readFile(filePath, (err, content) => {
        if (err) {
            fs.readFile(path.join(__dirname, 'public', 'error.html'), (err, data) => {
                if (err) {
                    res.writeHead(500)
                    res.end('Error')
                } else {
                    res.writeHead(200, {
                        'Content-Type': 'text.html'
                    })

                    res.end(data)
                }
            })
        } else {
            res.writeHead(200, {
                'Content-Type': contentType
            })

            dbConnect()

            if (req.url === '/login' && req.method === 'POST') {
                loginApp(req, res)
            } else if (req.url === '/registration' && req.method === 'POST') {
                regApp(req, res)
            } else if (req.url === '/new_post' && req.method === 'POST') {
                createNewPost(req, res)
            } else if (req.url === '/main' && req.method === 'POST') {
                deletePost(req, res)
            } else if (req.url === '/main' && req.method === 'GET') {
                let rubric = url.parse(req.url, true).query.rubric
                console.log("rubric: " + rubric) //undefined
                renderPosts(res, rubric)
            } else {
                res.end(content)
            }
        }
    })
})

const PORT = process.env.PORT || 5000
server.listen(PORT, () => {
    console.log(`Server has been started on ${PORT}...`)
})

async function renderPosts(res, rubric) {
    let card_data = ''

    await Post.find({rubric: rubric}, function(error, docs) { 
        if (error) return console.log(error)
        
        for (let i in docs) {
            card_data +=
            `<div class="post">
                <div class="post_header">
                    <input class="post_delete" type="image" src="img/bin-delete.png" post-id="${docs[i]._id}"/>
                    <tt class="post_date">${new Date(docs[i].date).toLocaleDateString()}</tt>
                    <tt class="post_rubric">${docs[i].rubric}</tt>
                </div>
                <h3 class="post_title">${docs[i].title}</h3>
                <p class="post_text">${docs[i].text}</p>
            </div>`
        }

        fs.readFile(__dirname + "/public/main.html", (err, data) => {
            if (err) return console.log(err)

            let updatedData = data.toString().replace('{card_data}', card_data)
            res.writeHead(200, {'Content-Type': 'text/html'})
            res.end(updatedData)
        })
    })
}

这样我们就得到了 main.html -> index .js -> main.html 链。

标签: javascriptnode.js

解决方案


看看这个逻辑:

} else if (req.url === '/main' && req.method === 'GET') {
    let rubric = url.parse(req.url, true).query.rubric
    console.log("rubric: " + rubric) //undefined

如果查询字符串与/main. 因此,如果它是/main?rubric=programming(即,如果它实际上有一个查询字符串),那么它将不匹配。

你在顶部有一个类似的问题:

let filePath = path.join(__dirname, 'public', req.url === '/' ? 'login.html' : req.url)

您需要解析 URL 并在服务器函数的最顶部分离出它的路径和查询组件。然后,您只需要根据路径组件进行路由。


推荐阅读