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

前端筛选方形媒体后无法渲染,Node.js后端无法检测尺寸求助

前端筛选图片/视频宽高比并在React中正确渲染的解决方案

需要筛选数组中图片/视频条目,过滤掉宽高比不在0.8-1.2范围内的内容,现有代码能在控制台输出筛选结果,但无法在React中正常渲染,尝试Promise.all和useState时遇到错误,包括“预期HTML,收到Promise”和“初始化过多React播放器”。

核心问题分析

原代码存在三个关键问题:

  • promises数组错误收集了验证结果(布尔值),而非Promise实例,导致Promise.all无法正确等待所有异步验证完成
  • 使用普通数组itemArray存储结果,React无法监听其变化,无法触发渲染
  • 视频验证时创建的DOM元素未清理,导致内存泄漏和播放器实例过多异常

修复后的完整代码

import { useState, useEffect } from 'react';

// 验证图片是否为方形(宽高比0.8-1.2)
function isImageSquare(url) {
  return new Promise((resolve) => {
    const img = new Image();
    img.onload = () => {
      const ratio = img.height / img.width;
      resolve(ratio >= 0.8 && ratio <= 1.2);
    };
    // 处理图片加载失败,默认标记为不符合
    img.onerror = () => resolve(false);
    img.src = url;
  });
}

// 验证视频是否为方形,完成后清理DOM元素避免内存泄漏
function isVideoSquare(url) {
  return new Promise((resolve) => {
    const video = document.createElement('video');
    
    const handleMetadataLoaded = () => {
      const ratio = video.videoHeight / video.videoWidth;
      resolve(ratio >= 0.8 && ratio <= 1.2);
      // 清理事件监听和DOM元素
      video.removeEventListener('loadedmetadata', handleMetadataLoaded);
      video.remove();
    };

    const handleError = () => {
      resolve(false);
      video.removeEventListener('loadedmetadata', handleMetadataLoaded);
      video.remove();
    };

    video.addEventListener('loadedmetadata', handleMetadataLoaded, false);
    video.addEventListener('error', handleError, false);
    video.src = url;
    // 仅加载元数据,无需播放
    video.load();
  });
}

function MediaGallery({ data }) {
  const [filteredItems, setFilteredItems] = useState([]);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const filterMediaItems = async () => {
      setIsLoading(true);
      
      // 为每个媒体项创建验证Promise,保留原始条目
      const validationTasks = data.map(async (item) => {
        let isSquare = false;
        switch(item.itemType) {
          case 'image':
            // 替换为item对应的图片URL字段
            isSquare = await isImageSquare(item.imageUrl);
            break;
          case 'video':
            isSquare = await isVideoSquare(item.videoUrl);
            break;
          case 'audio':
            // 如果音频无需筛选,直接标记为通过;若需验证封面图,自行补充逻辑
            isSquare = true;
            break;
          default:
            isSquare = false;
        }
        // 符合条件返回条目,否则返回null
        return isSquare ? item : null;
      });

      // 等待所有验证完成,过滤无效条目
      const validatedResults = await Promise.all(validationTasks);
      const validItems = validatedResults.filter(item => item !== null);
      
      setFilteredItems(validItems);
      setIsLoading(false);
    };

    filterMediaItems();
  }, [data]);

  // 加载状态提示
  if (isLoading) {
    return <div>正在筛选媒体内容...</div>;
  }

  // 渲染筛选后的内容
  return (
    <div className="media-container">
      {filteredItems.map((item) => (
        <div key={item.id} className="media-card">
          {item.itemType === 'image' && (
            <img src={item.imageUrl} alt="媒体内容" className="media-image" />
          )}
          {item.itemType === 'video' && (
            <video controls className="media-video">
              <source src={item.videoUrl} type="video/mp4" />
              您的浏览器不支持视频播放
            </video>
          )}
          {item.itemType === 'audio' && (
            <audio controls className="media-audio">
              <source src={item.audioUrl} type="audio/mpeg" />
              您的浏览器不支持音频播放
            </audio>
          )}
        </div>
      ))}
    </div>
  );
}

export default MediaGallery;

关键修复说明

  1. 正确收集Promise:使用data.map(async item => ...)生成所有验证任务的Promise数组,确保Promise.all能等待所有异步操作完成
  2. React状态管理:用useState存储筛选后的条目,一次性更新状态触发渲染,避免异步操作导致的状态不同步
  3. 清理DOM元素:视频验证完成后移除创建的video元素和事件监听,解决“初始化过多播放器”的问题
  4. 错误处理:添加图片/视频加载失败的回调,避免Promise一直处于pending状态
  5. 加载状态提示:通过isLoading状态展示加载中提示,提升用户体验

注意事项

  • 替换代码中item.imageUrl、item.videoUrl等字段为实际业务中的字段名
  • 若音频需要筛选(比如验证封面图),可补充对应的验证逻辑
  • 可根据需求调整宽高比的阈值(当前为0.8-1.2)

内容的提问来源于stack exchange,提问作者Syed Hashir Sohail

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 07:28:09