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

调用Flickr API后图片src属性undefined问题求助

解决Flickr API调用后图片URL多数为undefined的问题

嘿,我刚好碰到过一模一样的问题!你现在的情况是:明明photoGallery数组里已经有数据了,但渲染后大部分图片的src都是undefined,只有一张能正常显示。核心问题出在异步请求的时序没处理对,咱们一步步理清楚:

问题根源分析

你的代码里,判断是否调用displayImage的条件是searchReceived == searchRequests——这个条件只会判断「所有搜索图片的请求是否完成」,但完全没考虑「每个图片获取尺寸信息的getSizes请求是否全部完成」。

举个例子:你发起了5个搜索请求,当第5个搜索请求返回后,searchReceived就等于searchRequests了,这时候你立刻调用displayImage,但这时候可能只有1个getSizes请求刚好完成,剩下4个还在等待Flickr服务器响应,对应的imageObject.url_small还没被赋值,自然就是undefined。

解决方案:等待所有异步请求完成再渲染

我们需要新增一个计数器,专门统计所有getSizes请求的完成情况,只有当所有getSizes请求都拿到数据后,再执行渲染。

修改后的代码步骤:

  1. 新增全局计数器,用于追踪getSizes请求的总数和完成数:
let photoGallery = []; 
let searchRequests; 
let searchReceived;
let totalSizesRequests = 0; // 新增:统计所有需要发起的getSizes请求数
  1. 在searchFlickr开头重置计数器,避免多次搜索时数值累加:
function searchFlickr(searchArray) {
  photoGallery = [];
  searchRequests = searchArray.length;
  searchReceived = 0;
  totalSizesRequests = 0; // 重置计数器
  let flickr_searchStr = "";
  $('#Gallery figure').fadeOut();
  searchArray.forEach(function (element) {
    flickr_searchStr = "https://api.flickr.com/services/rest/?method=flickr.photos.search&sort=relevance&content_type=7&format=json&nojsoncallback=1&per_page=1&text=" + element + API_KEY 
    $.get(flickr_searchStr, function (data) {
      fetchImage(data);
    })
  })
}
  1. 在fetchImage里,每新增一个需要获取尺寸的图片,就把计数器加1:
function fetchImage(data) {
  searchReceived++
  for (let i = 0; i < data.photos.photo.length; i++) {
    let imageObject = {id: data.photos.photo[i].id,title: data.photos.photo[i].title}
    photoGallery.push(imageObject);
    totalSizesRequests++; // 每添加一个图片,就增加getSizes请求计数
    getSizes(imageObject);
  }
}
  1. 修改getSizes的回调逻辑,每次请求完成后减少计数器,当计数器为0时再渲染:
function getSizes(imageObject) {
  let getSizesStr = "https://api.flickr.com/services/rest/?method=flickr.photos.getSizes&format=json&nojsoncallback=1" + API_KEY + "&photo_id=" + imageObject.id;
  $.get(getSizesStr, function (data) {
    // 优化:通过label查找Small尺寸,避免依赖数组索引
    const smallSize = data.sizes.size.find(size => size.label === "Small");
    imageObject.url_small = smallSize ? smallSize.source : "";
    
    totalSizesRequests--;
    checkIfReadyToDisplay();
  })
  // 新增:处理请求失败的情况,避免计数器永远不为0
  .fail(function() {
    // 可以设置一个默认图片URL,或者留空
    imageObject.url_small = "";
    totalSizesRequests--;
    checkIfReadyToDisplay();
  });
}

// 抽成单独的判断函数,代码更清晰
function checkIfReadyToDisplay() {
  if (totalSizesRequests === 0) {
    displayImage(photoGallery);
  }
}

额外说明

刚才把data.sizes.size[3]改成了通过label查找Small尺寸,是因为Flickr返回的尺寸数组顺序有可能发生变化,用label匹配比依赖索引更可靠,能避免后续出现意外报错。

总结

本质上就是异步操作的顺序问题:不能只等第一层搜索请求完成,必须等所有第二层获取图片尺寸的请求都完成后,再去渲染页面。用计数器追踪所有异步请求的状态,就能完美解决这个问题啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:39:43