axios 和 promise,数组值不可用但出现在 console.log
Posted
技术标签:
【中文标题】axios 和 promise,数组值不可用但出现在 console.log【英文标题】:axios and promises, array value not available but appears in console.log 【发布时间】:2018-06-10 13:53:58 【问题描述】:我已经嵌套了 axios 调用,因此使用 Promise 来构建我将用于我的应用程序的数据数组。
第一次调用获取标题或剧集列表。
第二次调用获取第一次收到的剧集 url 以获取更多数据。然后,我将属性添加到我想在我的应用程序中使用的数据数组中。 这些是 title 和 image_urls[0]。
第三个调用然后获取 image_urls[0] 并调用以检索该实际图像。现在在这个调用中,当我 console.log 或对第二次调用中添加的值做任何事情时,我得到了未定义,但是如果我 console.log 我的完整数组出现了值!
console.log("sections", sections); // show all the data including 2nd call
console.log("image url", item.url); // This shows
console.log("image title", item.title); // This doesn't and don't know why
console.log("image imageurls", item.imageurls); // This doesn't and don't know why
这是我的代码
import axios from 'axios';
let sections = new Array(),
section = null,
episodes = null;
const dataService =
axios
.get('http://feature-code-test.skylark-cms.qa.aws.ostmodern.co.uk:8000/api/sets/coll_e8400ca3aebb4f70baf74a81aefd5a78/items/')
.then((response) =>
var data = response.data.objects;
Promise.all(data.map(function (item)
let type = item.content_type.toLowerCase();
if (type !== "episode")
if (section !== null)
section.episodes = episodes;
sections.push(section);
section = new Object();
episodes = new Array();
section.header = item.heading;
if (type === "episode")
var episode = new Object();
episode.url = item.content_url;
episodes.push(episode)
)).then(function ()
section.episodes = episodes;
sections.push(section);
Promise.all(sections.map(function (item)
Promise.all(item.episodes.map(function (item)
var url = `http://feature-code-test.skylark-cms.qa.aws.ostmodern.co.uk:8000$item.url`
axios
.get(url)
.then((response) =>
var data = response.data;
item.title = data.title;
item.imageurls = data.image_urls[0] !== undefined ? data.image_urls[0] : "";
);
))
)).then(function ()
Promise.all(sections.map(function (item)
Promise.all(item.episodes.map(function (item)
console.log("sections", sections);
console.log("image urr", item.url);
console.log("image title", item.title);
console.log("image imageurls", item.imageurls);
));
));
);;
)
)
export default dataService
【问题讨论】:
您继续使用map()
,但永远不会向这些映射数组返回任何内容。 Promise.all([undefined,undefined])
没用,不会等待任何东西。也不返回链式 then()
's 中的任何内容
@charlietfl 你能给我看一个修改上面代码的例子吗?
@charlietfl 我正在映射的数组,我正在 Promise 中更新。您能解释一下为什么在控制台记录sections 数组时会出现这些值,但在第三次调用中执行项目属性时却没有。
首先,仅在需要的地方使用 Promise - 代码的快速而肮脏的重写(我认为)是 jsfiddle.net/r7txrqo0 - 注意只有一个 Promise.all ...与 5 个不必要的 Promise 相比.all 在您的代码中? ...并使用 forEach,因为您的代码中根本不需要 .map - 然而,这是一个快速而肮脏的重写
你的代码可以写成jsfiddle.net/r7txrqo0/1 - 老实说,我仍然不理解或不喜欢第一个“循环”。而且,最后,dataService
将是一个解析为 undefined
的 Promise,与您的原始代码相同 - 因为我不知道您希望 dataService
实际上是什么
【参考方案1】:
以下应该对你有用,我认为你必须花一点时间来研究 promise、map 和 reduce。
我摆脱了 axios 并使用了 fetch,因此可以在网站上打开 api page 并在控制台中运行代码时在浏览器中对其进行测试(没有导出行并将 const 替换为 var)。
如果您需要任何帮助,请告诉我。
const base = "http://feature-code-test.skylark-cms.qa.aws.ostmodern.co.uk:8000";
const setEpisodeDetails = episode =>
fetch(`$base$episode.url`)
.then(response=>response.json())
.then(
data =>
Object.assign(
,episode
,
title : data.title,
imageurls : data.image_urls[0] || ""
)
)
.then(//fetch image url
episode =>
(episode.imageurls!=="")
? fetch(`$base$episode.imageurls`)
.then(response=>response.json())
.then(
imageData=>
Object.assign(
,
episode,
image_content_url:imageData.url
)
)
: episode
);
const setAllEpisodeDetails = sections =>
Promise.all(
sections.map(
section =>
Promise.all(
section.episodes.map(
setEpisodeDetails
)
)
.then(
episodes =>
Object.assign(
,
section,
episodes
)
)
)
);
const createSections = data =>
data.reduce(
(acc,item)=>
(item.content_type.toLowerCase()!=="episode")
? acc.push(header:item.heading,episodes:[])
: acc.slice(-1)[0].episodes.push(url:item.content_url)
return acc
,
[]
);
const dataService =
fetch(`$base/api/sets/coll_e8400ca3aebb4f70baf74a81aefd5a78/items/`)
.then(response=>response.json())
.then(
response =>
setAllEpisodeDetails(createSections(response.objects))
)
.then(
sections =>
console.log(
"sections",
JSON.stringify(sections,undefined,2)
) || //remove this console log if it works
// (can remove the whole last then)
//do not remove this it returns sections (unless you get rid of the whole then)
sections
);
//removed export, should log the result when done (or error)
【讨论】:
好的。不了解其中的大部分内容,因此将进行一些研究。将尝试在加载实际图像的 setEpisodeDetails 之后添加另一个调用 @Adam 如果您在现代浏览器中打开this link,您可以检查输出是否正确(最近的 Chrome 可以正常工作)。按 F12 并在控制台中粘贴代码。将export default dataService
替换为dataService.then(result=>console.log(JSON.stringify(result,undefined,2)))
是的,我可以看到它工作。不知道我如何扩展它以在 setEpisodeDetails 之后对 api 有另一个请求,以使用 episode.imageurls 检索实际图像。你能给我看看吗?
@Adam 您的意思是通过 fetch 获取图像并将其存储为 base64?我不知道该怎么做,但明天可以查一下。您可以尝试编写一个函数,该函数采用 url 并获取图像,将其存储为 base64 并将其设置为 img html 元素。您可以不下载图像,因为您有 url,因此您可以添加第一部分 (barurl.com...) 并将其用于您的 img src 属性。我不确定您的代码是否在 http://feature-code-test.skylark-cms.qa.aws.ostmodern.co.uk:8000
上运行,如果不是,代码可能根本无法工作,因为我没有看到允许来源的标头。
不是 base64。获取 episode.imageurls 的值是一个 api 端点。从该端点开始,属性之一是实际的绝对图像路径。所以我只需要 episode.imageurls 临时的,只是为了在那个电话之后得到实际的图像。以上是关于axios 和 promise,数组值不可用但出现在 console.log的主要内容,如果未能解决你的问题,请参考以下文章
从 Promise(ReactJS 和 Axios)中提取图像数据
使用 axios 时可能出现未处理的 Promise 拒绝、网络错误
Vue 接口 promise + fetch + axios + async 和 await