【问题标题】:Promise fetching data承诺获取数据
【发布时间】:2019-12-14 00:40:03
【问题描述】:

我想从该站点https://swapi.co/ 获取某些数据。 我使用 Promises 获取有关行星的数据,然后在某个行星对象内拍摄电影。之后,我需要在电影数组中的物种数组中获取数据。到目前为止一切正常。

我获取信息的代码:

const task = planetId => {
  const url = `https://swapi.co/api/planets/${planetId}/`;
  const getPlanet = () => { // getting the planet by its Id
    return new Promise(function(resolve, reject) {
      https
        .get(`${url}`, function(res) {
          res.on("data", function(d) {
            const planetData = JSON.parse(d.toString());
            resolve(planetData);
          });
        })
        .on("error", function(e) {
          reject(e);
          console.error(e);
        });
    });
  };
  getPlanet().then(gotPlanet => {
    const planet = gotPlanet;
    const filmsArray = planet.films;
    const filmsArrayUrl = filmsArray.map(it => {
      return new Promise(function(resolve, reject) { // getting films array
        https
          .get(it, function(res) {
            res.on("data", function(d) {
              const films = JSON.parse(d.toString());
              resolve(films);
            });
          })
          .on("error", function(e) {
            reject(e);
            console.error(e);
          });
      });
    });
    Promise.all(filmsArrayUrl).then(gotFilms => {
      const filmsNew = gotFilms;
      planet.films = filmsNew;
      const speciesArray = planet.films.map(it => it.species);
      const speciesArrayUrl = speciesArray.map(it => it.map(el => { // trying to get the species data
        return new Promise(function(resolve, reject) {
          https.get(el, function(res) {
            res.on('data', function(d) {
              const speciesFetched = JSON.parse(d.toString())
              resolve(speciesFetched)
            })
          }).on('error', function(e) {
            reject(e)
            console.error(e)
          })
        })
      }))
      Promise.all(speciesArrayUrl).then(species => {console.log(species)})
    });
  });
};

最后一行在控制台中显示为[Array[5], Array[20], Array[9]],数组中的每个元素为Promise {<pending>}。 我应该在代码中更改什么来获取所有物种对象并返回最终结果 - 一个带有电影和电影中物种的获取数据的星球?

【问题讨论】:

    标签: javascript promise


    【解决方案1】:

    您的代码很难遵循,我建议将可重用部分分解为他们自己的承诺,例如下面的 getDataObject 部分。然后,您可以在需要发出 HTTP 请求的任何时候重用该承诺。

    const getDataObject = url => fetch(url).then(res => res.json());
    
    const task = planetId => {
        const planetUrl = `https://swapi.co/api/planets/${planetId}/`;
        let planet
    
        return getDataObject(planetUrl)
            .then(planetResponse => {
                //get the planet response
                planet = planetResponse
    
                //map through each film in the planet and get its film
                let filmsArrayUrls = planet.films.map(filmUrl => getDataObject(filmUrl));
    
                return Promise.all(filmsArrayUrls)
            })
            .then(allFilms => {
                //update the planet with the response for each film
                planet.films = allFilms;
    
                //map through all the species in the films
                let speciesArray = planet.films.map(film => film.species);
    
                //map through the species elements using Promise.All
                let speciesArrayUrl = speciesArray.map(species => Promise.all(species.map(el => getDataObject(el))))
    
                //Promise.All is itself a Promise, so you still need to resolve the Array of Promise.All objects inside of the speciesArrayUrl
                return Promise.all(speciesArrayUrl)
          })
          .then(species => {
            //return the species and do something with them
            for (let i = 0; i < species.length; i ++) { 
                planet.films[i].species = species[i] 
            }
            console.log(planet)
            return planet
          })
      };
      
    task(2)

    【讨论】:

    • 感谢您的回复。我只需将这一行 planet.species = species 更改为 for (let i = 0; i &lt; species.length; i ++) { planet.films[i].species = species[i] } 现在它就像我想要的那样工作。
    • 谢谢,我用你建议的编辑更新了代码
    【解决方案2】:

    这是因为speciesArrayUrl 包含一个由一系列承诺组成的数组。您需要先展平数组。

    您可以做的一件事是通过附加.reduce((items, item) =&gt; items.concat(item), [])speciesArray 上应用reducer

    我使用fetch 重写了您的示例,以便它可以在浏览器中运行:

    const task = planetId => {
      const url = `https://swapi.co/api/planets/${planetId}/`;
      const getPlanet = () => { // getting the planet by its Id
        return fetch(url).then(res => res.json());
      };
      getPlanet().then(gotPlanet => {
        const planet = gotPlanet;
        const filmsArray = planet.films;
        const filmsArrayUrl = filmsArray.map(it => {
          return fetch(it).then(res => res.json());
        });
        Promise.all(filmsArrayUrl).then(gotFilms => {
          const filmsNew = gotFilms;
          planet.films = filmsNew;
          const speciesArray = planet.films.map(it => it.species)
            .reduce((items, item) => items.concat(item), []);
          const speciesArrayUrl = speciesArray.map(it => { // trying to get the species data
            return fetch(it).then(res => res.json());
          })
          Promise.all(speciesArrayUrl).then(species => {console.log(species)})
        });
      });
    };
    
    task(2);

    我还尝试重构代码以使其更具可读性:

    function getPlanet(planetId) {
      return fetch(`https://swapi.co/api/planets/${planetId}/`)
        .then(res => res.json());
    }
    
    function getFilms(planet) {
      return Promise.all(planet.films.map(f => fetch(f).then(res => res.json())));
    }
    
    function getSpecies(film) {
      return Promise.all(film.species.map(s => fetch(s).then(res => res.json())));
    }
    
    getPlanet(2)
      .then(planet => getFilms(planet))
      .then(films => Promise.all(films.map(film => getSpecies(film))))
      .then(filmSpecies => [].concat(...filmSpecies)) // flatten array of films and film species
      .then(species => {
        console.log(species);
      });

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-12
      • 2021-02-24
      • 2018-06-04
      • 2018-12-24
      • 1970-01-01
      • 2018-05-16
      • 2016-05-14
      • 1970-01-01
      相关资源
      最近更新 更多