node.js - 另一个 "can' t 在发送后设置 header ”

标签 node.js express sparql

我收到“发送后无法设置 header ”错误,我理解这可能是由于多次从我的服务器发送响应造成的,但我的代码似乎并非如此,至少表面上是这样。我向 dbpedia 进行查询以获得一些资源,然后将其发送回我的客户端。代码如下:

app.get("/",function(req,res,next){
    if (req.query.titolo){
        var response ;
        let [ artist, title ] = getArtistTitle(req.query.titolo);
        title = title.replace(" ","_");//for dbpedia resource names
        const prefixes = {
            dbo: "http://dbpedia.org/ontology/",
            db: "http://dbpedia.org/resource/"
        }
        DbPediaClient.setOptions('application/sparql-results+json',prefixes);
        DbPediaClient.query("SELECT ?abstract WHERE { db:"+title+
        " dbo:abstract ?abstract. FILTER langMatches(lang(?abstract),'en') }")
        .then((data)=>{
            response = data["results"]["bindings"][0]["abstract"]["value"] ;
            return res.json({abstract: response}) ;
        })
        .catch((error)=>{
            console.log(error);
        });
    }
});

我使用 virtuoso-sparql-client 来查询 http://dbpedia.org/sparql (DbPediaClient 在此函数之外初始化)。我已经尝试使用 res.send 而不是 res.json,但它仍然给出相同的错误。顺便说一句,如下:

Error: Can't set headers after they are sent.
    at validateHeader (_http_outgoing.js:491:11)
    at ServerResponse.setHeader (_http_outgoing.js:498:3)
    at ServerResponse.header (/home/lorenzo/Scrivania/ProgettoTechweb/AlphaTube/node_modules/express/lib/response.js:767:10)
    at ServerResponse.send (/home/lorenzo/Scrivania/ProgettoTechweb/AlphaTube/node_modules/express/lib/response.js:170:12)
    at DbPediaClient.query.then (/home/lorenzo/Scrivania/ProgettoTechweb/AlphaTube/server.js:43:15)
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

如果您需要更多信息,请询问。

最佳答案

Express 是一个框架,它通过迭代与 HTTP 请求中指定的路径匹配的路由来处理请求/响应周期,并让您的代码在每次匹配中发送响应,或者在满足条件时调用 next()没有寄出一份。这里的问题是您有以下情况:

app.get("/",function(req,res,next){
    res.sendFile(...);
    next();
});

app.get("/",function(req,res,next){
    if (req.query.titolo){
        ...
        res.json(...);
    }
});

这段代码的意思

Whenever I get an HTTP request to / then send some HTML, then if the request contains titolo in the query, send some JSON as well.

Express 告诉您,由于您已经发送了 HTML,因此您无法发送其他任何内容。

一种解决方案是将 API 路由移至 HTML 之上:

app.get("/",function(req,res,next){
    if (req.query.titolo){
        ...
        res.json(...);
    } else {
      next();
    }
});

app.get("/",function(req,res){
    res.sendFile(...);
});

这意味着

Whenever I get an HTTP request to /, if the request contains titolo in the query, send some JSON, otherwise send some HTML.

但我的建议是将 API 路由移动到不与静态文件的路由冲突的其他路径,这对于 HTTP 服务器来说更为典型。

关于node.js - 另一个 "can' t 在发送后设置 header ”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52538353/

相关文章:

javascript - 获取 nodejs 错误的行号

javascript - 无法使用express.Router 提供静态文件?

sparql - 使用 SPARQL 从维基数据获取所有电影片名的问题

javascript - 如何用 Promise 转回调函数

node.js - Nodejs 使用串口向 Arduino 发送数据

react-native - 如何将 react-native 图像从 expo-image-picker 上传到使用 multer 的 Express.js 后端

javascript - 如何在Nodejs中的多个文件中使用一个库

java - 在 Virtuoso 服务上使用 Jena 的 SPARQL 查询执行时间

sparql - 使用 WikiData Sparql 高效查询抽象元素

node.js - 使用 Botframework 进行 OAuth 时的神奇代码。有办法吗?