【问题标题】:Rithim Asynchronous Javascript exercises using fetch and promisesRithim 使用 fetch 和 Promise 的异步 Javascript 练习
【发布时间】:2020-01-17 09:59:24
【问题描述】:

我多年来一直坚持做这个练习,我终于认输并寻求帮助。

对星球大战 API [https://swapi.co/] 进行 AJAX 调用,并获取该系列中每部电影的开场抓取。完成此操作后,循环遍历每部电影的行星数组,并进行更多 AJAX 调用以收集按电影组织的每个行星的名称。然后,控制台记录一组对象,其中每个对象都包含特定电影的开场爬行,以及该电影中出现的每个行星的名称。

我已经阅读了一些关于异步 js 的文章并观看了一些视频,我“认为?”,我有点明白了。不过这真的不想工作。

    var promiseList = [];

    var fetchArray = function(arr) {
      promiseArr = arr
        .map(url => fetch(url)
            .then(res => res.json())
            .then(planet => planet.name)
            );     
      Promise.all(promiseArr)
        .then(data => console.log(data));
    }
    // fetchArray doesn't work at all. Curious if it's possible to run this code as it's technicall synchronous (idk).

    for (let number = 1; number < 8; number ++) {
      var t = fetch(`https://swapi.co/api/films/${number}/`)
       .then(res => res.json())
        promiseList.push(t)
    }

    console.log("NAHANH", promiseList)
    // Prints out [[object Promise] { ... }, [object Promise] { ... }, [object Promise] { ... }, [object Promise] { ... }, 
    [object Promise] { ... }, [object Promise] { ... }, [object Promise] { ... }]

    Promise.all(promiseList)
      .then(films => films.map(film => ({
        "title": film.title,
        "planets": film.planets,
        "opening_crawl": film.opening_crawl,
      })))
    // Works up untill this point, this next then doesn't work, my aim is to alter the film.plants property in every 
    array object and actually fetch the planet rather than just the url!
    // An example print out would be...
    // {
    //  opening_crawl: "Luke Skywalker has vanis...",
    //  planets: ["https://swapi.co/api/planets/61/"],
    //   title: "The Force Awakens"
    //  }]
      .then(films => films.map(film => {
          film.planets = film.planets
            .map(url => fetch(url)
              .then(res => res.json())
              .then(planet => planet.name)
              .catch(error => console.log(error.message))
            );     
      }
      .then(data => console.log(data))
    // Which would then finally resolve to (this is what I want but cannot get at the moment!) 
    //  {
    //    opening_crawl: "Luke Skywalker has vanis...",
    //    planets: ["Yavin IV"],
    //    title: "The Force Awakens"
    //  }]

它几乎可以返回一个对象。提取数组根本不起作用。并且我尝试检索行星名称的第二次更改不起作用。

【问题讨论】:

标签: javascript ajax promise fetch


【解决方案1】:

首先,将函数 fetchArray 重命名为 fetchPlanetNames,就像它所做的那样,并添加几个缺失的返回值。然后你有一个工作函数,它使主代码块更简单(正如你的意图:-))。

在主代码块中,fetchPlanetNames(...) 返回 Promise,而不是 Array,因此,在 films.map() 函子内,您需要 fetchPlanetNames(film.planets).then(planets =&gt; {/* compose the required film object here */})。这是您尝试过的一种“由内而外”的版本。

var fetchPlanetNames = function(arr) {
	return Promise.all(arr.map(url => { // return the Promise returned by Promise.all(...).then(...)
     // ^^^^^^
		return fetch(url)
		.then(res => res.json())
		.then(planet => planet.name);
	}))
	.then(data => {
		console.log(data);
		return data; // Remember to return `data`, otherwise undefined will be dlivered.
	     // ^^^^^^^^^^^^
	});
};

var promiseList = [];
for (let number = 1; number < 8; number ++) {
	promiseList.push(fetch(`https://swapi.co/api/films/${number}/`).then(res => res.json()));
}
Promise.all(promiseList)
.then(films => {
	return Promise.all(films.map(film => {
		// Here, a nested Promise chain allows `film` to remain in scope at the point where 'planets' become available.
		return fetchPlanetNames(film.planets)
		.then(planets => {
			return {
				'title': film.title,
				'planets': planets,
				'opening_crawl': film.opening_crawl
			};
		});
	}));
})
.then(data => console.log(data));

【讨论】:

    猜你喜欢
    • 2018-01-14
    • 2019-07-23
    • 1970-01-01
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    • 1970-01-01
    • 2021-05-28
    • 2021-06-28
    相关资源
    最近更新 更多