You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js循环引用转JSON错误:依赖POST的GET请求排查

错误详情

完整错误信息如下:

TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Socket'
    |     property 'parser' -> object with constructor 'HTTPParser'
    --- property 'socket' closes the circle
需求与实现

我想要实现一个依赖POST请求的GET查询功能,具体代码如下:

const postPrinterData = (request, response) => {
  const printer_id = parseInt(request.body.printer_id, 10);
  
  console.log('收到printer_id:', printer_id);

  getPrinter_material(printer_id, response);
};

const getPrinter_material = (printer_id, response) => {
  pool.connect((error, client, release) => {
    if (error) {
      throw error;
    }

    const query = {
      text: 'SELECT pr.printer_id, m.material FROM printer_material pm JOIN printer pr ON pm.printer_id = pr.printer_id JOIN material m ON pm.material_id = m.material_id WHERE pr.printer_id = $1;', 
      values: [printer_id],
    }

    client.query(query, (error, results) => {
      release();

      if (error) {
        throw error;
      }

      response.json([...results.rows]);
    });
  });
};
module.exports = {
  getPrinter_material,
  postPrinterData,
};
代码导出配置
const http = require('http');
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const db = require('./pool');

const app = express();
const port = 3000;

app.use(bodyParser.json());
app.use(
  bodyParser.urlencoded({
    extended: true,
  })
);

app.use(cors());

app.get('/printer_material', db.getPrinter_material);

app.post('/printerData', db.postPrinterData);

http.createServer(app).listen(port, () => {
  console.log(`应用运行在端口 ${port}。`);
});
排查尝试

我用下面的代码做了排查:

console.log(results);
console.log(JSON.stringify(results)); 

确认查询结果存在且能正常转为JSON格式,但还是出现了上面的循环引用转JSON错误,搞不懂问题出在哪。

前端代码
const selectElement1 = document.getElementById('select1');
const selectElement2 = document.getElementById('select2');
const selectElement3 = document.getElementById('select3');
const departmentSelect = document.querySelector('#department');

function createOption(value, text) {
  const option = document.createElement('option');
  option.value = value;
  option.textContent = text;
  return option;
}

function loadSelectOptions1(url, selectElement) {
  fetch(url)
    .then(response => response.json())
    .then(data => {
      data.forEach(item => {
        const option = createOption(item.printer_id, item.printer);
        selectElement.appendChild(option);
      });
    })
    .catch(error => {
      console.error(error);
      // 处理错误
    });
}

function loadSelectOptions2(url, selectElement) {
  fetch(url)
    .then(response => response.json())
    .then(data => {
      data.forEach(item => {
        const option = createOption(item.printer_id, item.material);
        selectElement.appendChild(option);
      });
    })
    .catch(error => {
      console.error(error);
      // 处理错误
    });
}

function loadPrinters() {
  loadSelectOptions1('http://:3000/printerCB', selectElement2);
}

function loadMaterial() {
  loadSelectOptions2('http://:3000/printer_material_defolt', selectElement3);
}

window.addEventListener('DOMContentLoaded', () => {
  loadPrinters();
  loadMaterial();
});

Promise.all([
  fetch('http://:3000/departament').then(response => {
    if (!response.ok) {
      throw new Error('数据加载错误');
    }
    return response.json();
  }),
  fetch('http://:3000/type_work').then(response => {
    if (!response.ok) {
      throw new Error('数据加载错误');
    }
    return response.json();
  })
])
  .then(([departamentData, typeWorkData]) => {
    const departamentOptions = departamentData.map(item => createOption(item.departament, item.departament));
    departmentSelect.append(...departamentOptions);

    const typeOptions = typeWorkData.map(item => createOption(item.type_work, item.type_work));
    selectElement1.append(...typeOptions);

    selectElement1.addEventListener('change', () => {
      const selectedValue = selectElement1.value;

      selectElement2.innerHTML = '';

      if (selectedValue === '黑白打印') {
        loadSelectOptions1('http://:3000/printerCB', selectElement2);
      } else if (selectedValue === '彩色打印') {
        loadSelectOptions1('http://:3000/printerColor', selectElement2);
      }
    });
  })
  .catch(error => {
    console.error(error);
  });

selectElement2.addEventListener('change', () => {
  const selectedPrinter = selectElement2.value;

  // 发送选中的printer_id到服务器
  fetch('http://:3000/printerData', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ printer_id: selectedPrinter })
  })
  .then(response => {
    if (!response.ok) {
      throw new Error('数据发送错误');
    }
  })
  .catch(error => {
    console.error(error);
  });
});

内容的提问来源于stack exchange,提问作者Andrey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 21:36:02