首页 > 解决方案 > Promise.all() 并不总是解决 - 编辑以添加两个函数的代码

问题描述

我正在使用以下代码来更新状态,但 Promise.all() 数组并不总是在调用最终函数之前被解析。有时,整个数组都会被填充,但通常不会。

我将 Promise.all() 数组记录到控制台,这样我就可以看到发生了什么。真正奇怪的是状态总是正确更新,但调用数组中的各个元素通常会返回“未定义”。我需要使用各个元素来创建一个新数组以便稍后显示,这就是我访问它们的原因。

请帮助我弄清楚如何在完成更新后访问数组,或者更好地处理整个事情。

class X {
  componentDidMount() {
    const numTiles = 3;

    for (let i = 0; i < numTiles; i++) {
      Promise.all([
        this.fetchSong(), // returns JSON from SQLite DB
        this.fetchArtists(),  // returns JSON from SQLite DB
      ]) 
        .then(values => {
          this.testing(values);
        });
    }
  }

  testing(arr) {
    console.log("arr: ", arr);
    console.log("arr[0]: ", arr[0]);
    console.log("arr[0].id: ", arr[0].id);
    console.log("arr[0].name: ", arr[0].name);
    console.log("arr[0].artist: ", arr[0].artist);
    console.log("arr[1]: ", arr[1]);
    console.log("arr[1][0]: ", arr[1][0]);
    console.log("arr[1][1]: ", arr[1][1]);
    console.log("arr[1][0].artist: ", arr[1][0].artist);
    console.log("arr[1][1].artist: ", arr[1][1].artist);
  }
}

编辑:添加了 fetchSong() 和 fetchArtists() 的代码。

fetchSong() {
    let id = Math.floor(Math.random() * 2000) + 1;  // get random number for id
    return new Promise((resolve, reject) => {
      Bingo.getSong(id).then(song => {
        resolve(song);
      });
    });
  }

  fetchArtists() {
    return new Promise((resolve, reject) => {
      let arr = [];
      for (let j = 0; j < 2; j++) {
        let id = Math.floor(Math.random() * 10) + 1;
        Bingo.getArtist(id).then(artist => {
          arr.push(artist);
        });
        resolve(arr);
      };
    });
  }

下面的控制台屏幕截图显示 Promise.all() 数组已被填充,但数组元素仍然缺失。

控制台截图

标签: javascriptarraysreactjspromise

解决方案


问题在于 的实现fetchArtists,它在任何单艺术家获取承诺被解决之前就解决了。

我也简化fetchSong了,但现在的要点fetchArtists是你存储将解决单个艺术家的承诺,然后等待所有这些都解决。没有理由在此处添加 a .then(),因为如您所知,Promise.all()无论如何都会使用已解析值的数组进行解析。

fetchSong() {
  const id = Math.floor(Math.random() * 2000) + 1;
  return Bingo.getSong(id);
}

fetchArtists() {
  const fetchPromises = [];
  for (let j = 0; j < 2; j++) {
    const id = Math.floor(Math.random() * 10) + 1;
    fetchPromises.push(Bingo.getArtist(id));
  }
  return Promise.all(fetchPromises);
}

推荐阅读