JavaScript使用fetch请求API返回[object Promise]无法获取实际值
问题描述
刚接触Promise,尝试在网页上展示接口返回对象的实际值时,页面仅显示[object Promise],无法得到真实数据。
现有代码
// This section fetches the api results and puts them into a list/array async function getitglinkquery(){ var linkresults = await parseitgsearchquery(); console.log(linkresults); // var linkresultvalues = []; for (let i = 0; i < linkresults.length; i++) { var linkresultvalues = fetch(linkresults[i], { method: "GET", withCredentials: true, headers: { // needed to base64 encode my key with ":x" at the end of the api key then I used that for the authorization header. "x-api-key": "INSERTAPITHINGYHERE"}}) .then(response => response.json()) } return linkresultvalues; } // This section is trying to get the promise and parse the results async function parseitglinkquery() { var queriedresults = await getitglinkquery(); console.log(typeof queriedresults); // linkresultvalues.push(response); const output = document.querySelector('span.ms-font-mitglue'); let pre = document.createElement('p'); pre.innerHTML = queriedresults; pre.style.cssText += 'font-size:24px;font-weight:bold;'; output.appendChild(pre); } parseitglinkquery();
已尝试的解决方案
- 使用
Promise.resolve方法包裹请求函数,没有生效:
async function parseitglinkquery() { var queriedresults = await Promise.resolve(getitglinkquery()); console.log(queriedresults); }
- 尝试使用
Promise.all()直接报错,变量类型检查返回object:
async function parseitglinkquery() { var queriedresults = await Promise.all(getitglinkquery()); }
报错信息:
Uncaught (in promise) TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
- 尝试通过
.then获取结果也报错:
queriedresults.then(function(result){ console.log(result) })
报错信息:
Uncaught (in promise) TypeError: queriedresults.then is not a function
问题原因
- 异步逻辑存在循环调用,两个函数互相等待,执行逻辑完全混乱
- 循环请求时没有把所有fetch返回的Promise存入数组,每次都直接覆盖
linkresultvalues变量,最终函数只返回最后一个请求的Promise对象,不是可迭代的数组,所以调用Promise.all会报错 - 已经使用
await等待异步结果的前提下,再使用Promise.resolve属于多余操作,对结果没有影响 - 拿到接口返回的对象后直接赋值给DOM的innerHTML属性,对象会被默认转为
[object Object]字符串,无法展示真实内容
修复后的代码
// 单独抽离请求批量接口的逻辑 async function getitglinkquery(){ // 先获取所有需要请求的链接列表 var linkresults = await parseitgsearchquery(); console.log(linkresults); // 定义数组存储所有请求的Promise const linkresultvalues = []; for (let i = 0; i < linkresults.length; i++) { // 把每个请求的Promise push到数组里 const reqPromise = fetch(linkresults[i], { method: "GET", withCredentials: true, headers: { "x-api-key": "INSERTAPITHINGYHERE" } }).then(response => response.json()) linkresultvalues.push(reqPromise) } // 等待所有请求完成后返回结果数组 return Promise.all(linkresultvalues); } // 渲染结果到页面的逻辑 async function parseitglinkquery() { // 直接等待所有接口返回结果 var queriedresults = await getitglinkquery(); console.log(queriedresults); const output = document.querySelector('span.ms-font-mitglue'); let pre = document.createElement('p'); // 把对象数组转为格式化的JSON字符串展示,也可以根据需求遍历提取字段 pre.innerHTML = JSON.stringify(queriedresults, null, 2); pre.style.cssText += 'font-size:24px;font-weight:bold;white-space: pre-wrap;'; output.appendChild(pre); } parseitglinkquery();
关键修改说明
- 拆分了循环调用的逻辑,避免两个函数互相等待导致的异常
- 用数组存储所有接口请求的Promise,通过
Promise.all批量等待所有请求完成,拿到完整的结果数组 - 把返回的对象数组通过
JSON.stringify转为格式化字符串后再插入DOM,保证内容可以正常展示 - pre标签增加
white-space: pre-wrap样式,保证JSON格式化后的缩进可以正常显示
内容的提问来源于stack exchange,提问作者user16660683
相关产品推荐
相关产品推荐

