为什么此数组为空?

时间:2019-04-03 16:59:45

标签: javascript reactjs react-native

我正在通过我的Firebase应用程序在Firebase上获取某些数据。

我进行了三次检查,并调试了代码。第一次读取将返回数组中的5个项目。然后,我需要获取用户的ID并进行另一次提取,以从用户那里获取数据。这是我的代码:

export const fetchStyleItems = () => async dispatch => {
  dispatch({ type: GET_STYLE_ITEMS_REQUEST });
  database
    .ref("styles_items")
    .orderByChild("posted")
    .once("value")
    .then(function(snapshot) {
      const exists = snapshot.val() !== null;
      if (exists) data = snapshot.val();
      var photo_feed = [];
      for (var photo in data) {
        const photoObj = data[photo];
        database
          .ref("users")
          .child(photoObj.author)
          .once("value")
          .then(function(snapshot) {
            const exists = snapshot.val() !== null;
            if (exists) data = snapshot.val();
            console.log(`inside the lasso ${photoObj} `);
            photo_feed.push({
              id: photo,
              url: photoObj.url,
              caption: photoObj.caption,
              name: photoObj.name,
              price: photoObj.price,
              style_recomendation: photoObj.style_recomendation,
              style_type: photoObj.style_type,
              posted: photoObj.posted,
              author: data.username
            });                   

            });
          })
          .catch(error => console.log(error));
      }
      console.log();
      dispatch({
        type: GET_STYLE_ITEMS_SUCCESS,
        payload: photo_feed
      });
    })
    .catch(error => console.log(error));
};

问题。当我调试代码并尝试调度GET_STYLE_ITEMS_SUCCESS时,数组photo_feed将为空。

我认为我在这里缺少一些范围。但是我现在停留了3个小时,看不到出了什么问题。

3 个答案:

答案 0 :(得分:1)

我认为您是在for循环中迭代数组并进行异步调用,但您没有等待这些异步调用。因此,在您要调度数组时,photo_feed为空

具体在这里

for (var photo in data) {
        const photoObj = data[photo];
        database
          .ref("users")
          .child(photoObj.author)
          .once("value")
          .then(function(snapshot) {
           // this is async
          })

所以您应该等待这些承诺。此外,您的函数是异步的,但是您使用的是可链接的.then()方法,而不是等待(这是添加异步的目的)。因此,我做了一些改写,并用var

替换了您的let
export const fetchStyleItems = () => async dispatch => {
  try {
    dispatch({ type: GET_STYLE_ITEMS_REQUEST });
    let snapshot = await database
      .ref("styles_items")
      .orderByChild("posted")
      .once("value");
    const exists = snapshot.val() !== null;
    if (exists) { 
      data = snapshot.val();
    }
    let photo_feed = [];
    for (let photo in data) {
      const photoObj = data[photo];
      let snapshot = await database
        .ref("users")
        .child(photoObj.author)
        .once("value");
      const exists = snapshot.val() !== null;
      if (exists) {
        data = snapshot.val()
      };
      photo_feed.push({
        id: photo,
        url: photoObj.url,
        caption: photoObj.caption,
        name: photoObj.name,
        price: photoObj.price,
        style_recomendation: photoObj.style_recomendation,
        style_type: photoObj.style_type,
        posted: photoObj.posted,
        author: data.username
      });
    }
    dispatch({
      type: GET_STYLE_ITEMS_SUCCESS,
      payload: photo_feed
    });   
  }
  catch (e) {
    console.log(e);
  }
};

进一步了解asyncawait

我不确定100%等待for..in是否可以正常工作(我相信可以);但是,如果没有,则可以用for..of循环加上Object.keys(data)

来代替

答案 1 :(得分:0)

您的for循环正在对数据中的每张照片进行异步调用->在进行下一次调用以获取照片对象之前,您不必等待调用返回。您要获取第一个数据项的照片对象,然后在返回时获取下一个照片数据项的照片对象。

此代码导致了您的问题:

for (var photo in data) {
        const photoObj = data[photo];
        database
          .ref("users")
          .child(photoObj.author)
          .once("value")
          .then(function(snapshot) {
            const exists = snapshot.val() !== null;
            if (exists) data = snapshot.val();
            console.log(`inside the lasso ${photoObj} `);
            photo_feed.push({
              id: photo,
              url: photoObj.url,
              caption: photoObj.caption,
              name: photoObj.name,
              price: photoObj.price,
              style_recomendation: photoObj.style_recomendation,
              style_type: photoObj.style_type,
              posted: photoObj.posted,
              author: data.username
            });                   

            });
          })
          .catch(error => console.log(error));
      }

答案 2 :(得分:0)

由于结果是异步的,因此您需要等待结果分派。您可以将所有的Promise映射到一个数组,然后使用Promise#all。喜欢

const photoFeedPromises = data.map(photoObj => {
  return database
    .ref("users")
    .child(photoObj.author)
    .once("value")
    .then(function(snapshot) {
      const exists = snapshot.val() !== null;
      if (exists) data = snapshot.val();
      console.log(`inside the lasso ${photoObj} `);
      return { snapshot }; // Or whatever you need
    })
    .catch(error => console.log(error));
});

Promise.all(photoFeedPromises).then(results => {
  const photo_feed = results.filter(result => result !== undefined);
  dispatch({
    type: GET_STYLE_ITEMS_SUCCESS,
    payload: photo_feed
  });
});

您需要使用我发布的此代码段替换代码中的for循环和对dispatch的调用。