如何获取Promise内部then函数的返回结果?
解决异步获取stream状态的问题
你遇到的核心问题是异步操作的时序问题:$.getJSON返回的是一个Promise对象,而不是直接的结果,所以你打印的online其实是未完成的Promise,而不是onlineResult.stream的值。另外,forEach不会等待异步操作完成,所以你往listItems里push的时候,stream状态还没获取到。
下面是调整后的代码,我会一步步解释改动点:
var baseUrl = "https://wind-bow.gomix.me/twitch-api"; var channels = [ "ESL_SC2", "OgamingSC2", "cretetion", "freecodecamp", "storbeck", "habathcx", "RobotCaleb", "noobs2ninjas" ]; function fetchChannels(channels) { var listItems = []; if (Array.isArray(channels)) { // 第一步:获取所有channel的基础信息 const channelPromises = channels.map(channel => $.getJSON(`${baseUrl}/channels/${channel}?callback=?`) ); Promise.all(channelPromises) .then(channelValues => { // 第二步:对每个channel,同时获取stream状态,返回包含所有信息的Promise const streamPromises = channelValues.map(val => { return $.getJSON(`${baseUrl}/streams/${val.name}?callback=?`) .then(onlineResult => { // 把基础信息和stream状态合并,为空时返回null return { name: val.name, logo: val.logo, stream: onlineResult.stream || null }; }); }); // 第三步:等待所有stream状态请求完成 return Promise.all(streamPromises); }) .then(fullChannelData => { // 这里fullChannelData是包含所有信息的数组,每个元素都有name、logo、stream listItems = fullChannelData; console.log(listItems); // 现在可以拿到正确的结果了 // 这里可以继续处理listItems,比如渲染到页面 }) .catch(err => { // 别忘了处理错误! console.error("请求出错:", err); }); } } fetchChannels(channels);
关键改动说明:
- 把
forEach换成map,让每个异步操作返回Promise,这样可以用Promise.all等待所有请求完成 - 在每个stream请求的
then里,把channel基础信息和stream状态合并,确保最终能拿到完整的数据 - 多一层
Promise.all来等待所有stream请求完成,保证所有数据都准备好再处理 - 增加了
catch块处理请求失败的情况,避免静默错误
为什么原来的代码不行?因为let online = $.getJSON(...).then(...)里,online是Promise对象,只有当Promise状态变为resolved时,then里的函数才会执行,而你在console.log(online)的时候,这个Promise还没完成,所以看不到期望的结果。
如果想在fetchChannels外部拿到listItems,可以让函数返回Promise:
function fetchChannels(channels) { if (!Array.isArray(channels)) { return Promise.reject("参数必须是数组"); } const channelPromises = channels.map(channel => $.getJSON(`${baseUrl}/channels/${channel}?callback=?`) ); return Promise.all(channelPromises) .then(channelValues => { const streamPromises = channelValues.map(val => { return $.getJSON(`${baseUrl}/streams/${val.name}?callback=?`) .then(onlineResult => ({ name: val.name, logo: val.logo, stream: onlineResult.stream || null })); }); return Promise.all(streamPromises); }); } // 使用方式: fetchChannels(channels) .then(listItems => { console.log(listItems); // 这里写渲染页面的逻辑 }) .catch(err => console.error(err));
这样你就能在外部拿到完整的结果啦~
内容的提问来源于stack exchange,提问作者sanders
相关产品推荐
相关产品推荐

