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

receivedImageUrl变量未更新求助:Node.js+EJS渲染API图片URL失败

解决Express中异步API调用后变量未赋值导致EJS渲染失败的问题

你遇到的核心问题是异步代码执行顺序导致的:response.on('end')是异步回调函数,当你在外部执行res.render时,回调里的receivedImageUrl赋值操作还没触发,所以变量还是初始的空字符串。下面给你三种直接可行的解决方法:


方法1:将渲染逻辑移到异步回调内部

把res.render放到response.on('end')的回调里,确保变量赋值完成后再渲染页面:

const https = require('https');
const express = require('express');
const app = express();

app.set('view engine', 'ejs');

app.get('/recipe', (req, res) => {
  let receivedImageUrl = '';
  // 替换为你的Edamam API完整地址
  const apiUrl = 'https://api.edamam.com/api/recipes/v2?type=public&app_id=YOUR_ID&app_key=YOUR_KEY&q=chicken';

  const request = https.get(apiUrl, (response) => {
    let data = '';

    response.on('data', (chunk) => {
      data += chunk;
    });

    response.on('end', () => {
      try {
        const recipeData = JSON.parse(data);
        receivedImageUrl = recipeData.hits[0].recipe.image;
        // 赋值完成后再渲染页面
        res.render('recipe', { imageUrl: receivedImageUrl });
      } catch (err) {
        console.error('解析API数据失败:', err);
        res.status(500).send('获取食谱图片失败');
      }
    });
  });

  request.on('error', (err) => {
    console.error('API请求失败:', err);
    res.status(500).send('请求食谱数据失败');
  });
});

app.listen(3000, () => console.log('服务器运行在3000端口'));

方法2:用Promise封装API调用,配合async/await

把HTTP请求封装成Promise,用async/await让异步代码逻辑更清晰:

const https = require('https');
const express = require('express');
const app = express();

app.set('view engine', 'ejs');

// 封装API请求为Promise
function fetchRecipeImage(apiUrl) {
  return new Promise((resolve, reject) => {
    const request = https.get(apiUrl, (response) => {
      let data = '';
      response.on('data', chunk => data += chunk);
      response.on('end', () => {
        try {
          const recipeData = JSON.parse(data);
          resolve(recipeData.hits[0].recipe.image);
        } catch (err) {
          reject(new Error('解析数据失败'));
        }
      });
    });
    request.on('error', reject);
  });
}

app.get('/recipe', async (req, res) => {
  try {
    const apiUrl = 'https://api.edamam.com/api/recipes/v2?type=public&app_id=YOUR_ID&app_key=YOUR_KEY&q=chicken';
    // 等待API请求完成,拿到图片地址
    const receivedImageUrl = await fetchRecipeImage(apiUrl);
    res.render('recipe', { imageUrl: receivedImageUrl });
  } catch (err) {
    console.error(err);
    res.status(500).send('获取食谱图片失败');
  }
});

app.listen(3000, () => console.log('服务器运行在3000端口'));

方法3:使用axios简化异步请求(可选)

如果不想手动封装Promise,可以用axios这类支持Promise的HTTP库,代码会更简洁:

const axios = require('axios');
const express = require('express');
const app = express();

app.set('view engine', 'ejs');

app.get('/recipe', async (req, res) => {
  try {
    const apiUrl = 'https://api.edamam.com/api/recipes/v2?type=public&app_id=YOUR_ID&app_key=YOUR_KEY&q=chicken';
    const response = await axios.get(apiUrl);
    const receivedImageUrl = response.data.hits[0].recipe.image;
    res.render('recipe', { imageUrl: receivedImageUrl });
  } catch (err) {
    console.error(err);
    res.status(500).send('获取食谱图片失败');
  }
});

app.listen(3000, () => console.log('服务器运行在3000端口'));

额外注意事项

  1. 替换代码中的YOUR_ID和YOUR_KEY为你自己的Edamam API凭证;
  2. EJS模板中要正确接收变量,比如:
<!-- views/recipe.ejs -->
<!DOCTYPE html>
<html>
<head>
  <title>食谱图片</title>
</head>
<body>
  <% if (imageUrl) { %>
    <img src="<%= imageUrl %>" alt="食谱图片" />
  <% } else { %>
    <p>暂无图片</p>
  <% } %>
</body>
</html>
  1. 一定要处理错误情况(API请求失败、数据解析失败等),避免服务器崩溃或页面无响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 14:01:40