Node.js “接收”;错误:Can';t在发送标题后设置标题。”;进行多个API调用时

Node.js “接收”;错误:Can';t在发送标题后设置标题。”;进行多个API调用时,node.js,api,express,Node.js,Api,Express,我正在重构一个Express项目,我需要进行多个API调用。我目前有9个单独的函数来进行每个单独的API调用,然后在每次API调用后将其设置为res.locals 我已经创建了一个数组,其中包含我需要访问的所有API URL,然后我有一个函数,该函数遍历该数组以进行所有的获取调用。但是,当我收到下面的消息时,我遇到了设置标题以使JSON数据能够通过的问题: 错误:发送邮件后无法设置邮件头。 根据我设置控制器的方式,我可以获取要在页面上呈现的控制器标头和第一个API响应,也可以仅获取要呈现的控制器

我正在重构一个Express项目,我需要进行多个API调用。我目前有9个单独的函数来进行每个单独的API调用,然后在每次API调用后将其设置为res.locals

我已经创建了一个数组,其中包含我需要访问的所有API URL,然后我有一个函数,该函数遍历该数组以进行所有的获取调用。但是,当我收到下面的消息时,我遇到了设置标题以使JSON数据能够通过的问题:

错误:发送邮件后无法设置邮件头。

根据我设置控制器的方式,我可以获取要在页面上呈现的控制器标头和第一个API响应,也可以仅获取要呈现的控制器标头。考虑到我的情况,我还没有找到解决这个问题的办法,我想知道是否有人提出了纠正这个问题的建议。我已经粘贴了我认为应该足够解决问题的代码,但是如果还有什么我可以提供的,请告诉我

API帮助文件(进行API调用的位置):

引入路由的服务器文件:

const cryptoRouter = require('./routes/crypto-routes')
app.use('/', cryptoRouter)

没有命中模型文件,因为此时数据库中没有插入任何内容。

好的,这里有一个问题:

function getData(req, res, next) {
    for (let i = 0; i < links.length; i ++) {
        fetch(links[i])
        .then(res => res.json())
        .then(fetchRes => {
            res.locals.i = fetchRes
            next()
        })        
        .catch(err => {
            res.json({err})
        })
    }
}
然后,在您的
.get()
路由处理程序中,我不知道您试图实现的结果类型的确切原因,但要返回结果数组,您可以执行以下操作:

cryptoController.sendApiData = (req, res) => { 
    console.log(res.locals.data)         
    res.json({
        message: 'data returned for crypto',            
        data: res.locals.data
    }); 
}

您必须为该控制器代码(整个请求处理程序以及在该请求处理程序中执行的任何代码)显示更多上下文,因为在这里显示它是没有意义的。您处于
for
循环中,将自定义函数分配给
cryptoController.sendApiData
,但不执行任何操作。另外,给同一个变量分配10个不同的函数也没有好处。只有最后一个将实际分配。另外,您也不会显示任何实际执行
cryptoController.sendApiData()
的代码。您看到的错误的一般原因是针对给定请求发送多个响应的代码。您只能发送一个响应。例如,对于给定的请求,只能调用
res.json()
一次。第一次调用它时,数据被转换为JSON,发送到客户机并关闭http连接。无法发送更多数据。如果我理解正确,我甚至无法使用异步函数来发送数据?异步函数与此无关。你真的需要向我们展示更多的代码,并描述你试图为我们做些什么,以更具体地帮助你。明白了。我刚刚更新了我的原始帖子,以显示路由和完整的控制器文件,以及如何在server.js文件中启动路由。澄清一下:我目前有9个API调用正在获得它们自己的函数(总共9个函数)。我正在尝试重构,以便所有API调用都可以在一个函数中进行,从而减少编写的代码量。非常感谢您的回复,并让我知道是否有任何其他信息/澄清我可以发送。这成功了!非常感谢你在这方面的帮助,有一段时间我真的对承诺感到困惑,但这个解释只是让它有点点击。
// import model
const Crypto = require('../models/Crypto')

// initiate controller object
const cryptoController = {}

// find latest cap coin entry
cryptoController.latest = (req, res, next) => {
    Crypto.findRecent()
    .then(crypto => {
        res.json({
            message: 'retrieved entry',
            data: { crypto }
        })
    }).catch(next)
}

// send api data
// for (let i = 0; i < 10; i ++) {  
cryptoController.sendApiData = (req, res) => { 
    console.log(res.locals)         
    res.json({
        message: 'data returned for crypto',            
        i: res.locals.i
    })  
    // }
}

// create new entry
cryptoController.create = (req, res) => {
    console.log(req.body, ' req.body from cryptoController#create')
    Crypto.create({
        // time made
        time_made: Date.now(),
        // crypto data
        usd: req.body.usd,
        us_high: req.body.us_high,
        us_low: req.body.us_low,
        eur: req.body.eur,
        eur_high: req.body.eur_high,
        eur_low: req.body.eur_low,
        trades: req.body.trades,
        one_hour: req.body.one_hour,
        one_day: req.body.one_day,
        seven_days: req.body.Seven_days,
        crypto_id: req.body.crypto_id
    })
}


module.exports = cryptoController
// import dependencies
const express = require('express')
const cryptoController = require('../controllers/crypto-controller')
const cryptoHelpers = require('../services/crypto-helpers')

// set router variable
const cryptoRouter = express.Router()

// set routes to fetch and store API data
cryptoRouter.post('/crypto', cryptoHelpers.getData, cryptoController.create)
cryptoRouter.get('/crypto', cryptoHelpers.getData, cryptoController.sendApiData)

module.exports = cryptoRouter;
const cryptoRouter = require('./routes/crypto-routes')
app.use('/', cryptoRouter)
function getData(req, res, next) {
    for (let i = 0; i < links.length; i ++) {
        fetch(links[i])
        .then(res => res.json())
        .then(fetchRes => {
            res.locals.i = fetchRes
            next()
        })        
        .catch(err => {
            res.json({err})
        })
    }
}
function getData(req, res, next) {
    let promises = links.map(function(link) {
        return fetch(link).then(res => res.json())
    });
    Promise.all(promises).then(results => {
        res.locals.data = results;    // res.locals.data is an array of link json
        next();
    }).catch(err => {
        res.status(500).json({err});
    });
}
cryptoController.sendApiData = (req, res) => { 
    console.log(res.locals.data)         
    res.json({
        message: 'data returned for crypto',            
        data: res.locals.data
    }); 
}