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

异步函数返回值赋值:基于FB SDK的电影信息HTML生成技术问询

Hey there! Let's work through that async value assignment issue you're hitting with your Facebook SDK app. From what you described, the core problem is almost certainly that you're trying to use results from async operations (like FB.api calls) synchronously—meaning the values aren't ready when you go to build your HTML blocks. Let's break down the fixes step by step.

First, let's clarify the common mistake that leads to this: if you’re using forEach with async functions, it won’t wait for each FB.api call to finish before moving to the next item. This leaves you trying to access values that haven’t been fetched yet, resulting in undefined or broken HTML.

Solution 1: Use async/await with for...of (Sequential Processing)

This approach processes each movie one after the other, ensuring you have all the data you need before building the HTML. We’ll wrap the callback-based FB.api in a Promise to make it compatible with await.

async function renderFavoriteMovies() {
  const favoriteMovies = data.favoriteMovies;
  
  // Loop through movies with for...of (it waits for await calls)
  for (const movie of favoriteMovies) {
    try {
      // Convert FB.api's callback to a Promise
      const pageData = await new Promise((resolve, reject) => {
        // Request only the fields we need (id + picture) to optimize performance
        FB.api(`/${movie.pageId}`, { fields: 'id,picture' }, (response) => {
          if (response.error) {
            reject(response.error);
          } else {
            resolve(response);
          }
        });
      });

      // Extract the data we need
      const pageLink = `https://facebook.com/${pageData.id}`;
      const avatarSrc = pageData.picture.data.url;
      const movieName = movie.name; // Assumes your 'data' includes the movie name

      // Build the HTML elements
      const article = document.createElement('article');
      
      const figure = document.createElement('figure');
      const img = document.createElement('img');
      img.src = avatarSrc;
      figure.appendChild(img);
      
      const div = document.createElement('div');
      const link = document.createElement('a');
      link.href = pageLink;
      link.textContent = movieName; // Add movie name as link text
      div.appendChild(link);
      
      // Assemble and add to the page
      article.appendChild(figure);
      article.appendChild(div);
      document.getElementById('movie-container').appendChild(article);

    } catch (error) {
      // Handle any failed API calls gracefully
      console.error(`Couldn't fetch data for ${movie.name}:`, error);
    }
  }
}

// Kick off the rendering
renderFavoriteMovies();

Solution 2: Use Promise.all (Parallel Processing)

If you don’t need to process movies in order, this method is faster—it sends all FB.api requests at once and waits for all to complete before building HTML.

async function renderFavoriteMovies() {
  const favoriteMovies = data.favoriteMovies;

  // Create an array of Promises for each movie's API call
  const movieDataPromises = favoriteMovies.map(movie => {
    return new Promise((resolve, reject) => {
      FB.api(`/${movie.pageId}`, { fields: 'id,picture' }, (response) => {
        if (response.error) {
          reject(response.error);
        } else {
          // Combine original movie data with fetched page data
          resolve({
            ...movie,
            pageLink: `https://facebook.com/${response.id}`,
            avatarSrc: response.picture.data.url
          });
        }
      });
    });
  });

  try {
    // Wait for all API calls to finish
    const moviesWithFullData = await Promise.all(movieDataPromises);

    // Build HTML for all movies at once
    moviesWithFullData.forEach(movie => {
      const article = document.createElement('article');
      
      const figure = document.createElement('figure');
      const img = document.createElement('img');
      img.src = movie.avatarSrc;
      figure.appendChild(img);
      
      const div = document.createElement('div');
      const link = document.createElement('a');
      link.href = movie.pageLink;
      link.textContent = movie.name;
      div.appendChild(link);
      
      article.appendChild(figure);
      article.appendChild(div);
      document.getElementById('movie-container').appendChild(article);
    });
  } catch (error) {
    console.error('Failed to fetch some movie data:', error);
  }
}

renderFavoriteMovies();

Key Notes to Avoid Future Headaches

  • Always specify the fields parameter in FB.api calls: This reduces the amount of data returned and ensures you get exactly what you need (no missing picture data!).
  • Never use async functions with forEach: forEach doesn’t respect async/await, so it’ll fire all requests at once without waiting for results.
  • Add error handling: Wrapping async code in try/catch prevents a single failed API call from breaking the entire rendering process.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 02:23:23