我有两个JSON。一种是来自变量,另一种是基于API的调用,我正在尝试生成HTML代码。我正在使用递归函数,因为JSON可以包含嵌套部分。这些JSON还可能包含多个“选择”,这些选择应基于另一个API调用(“源”)具有“选项”。当我尝试执行代码时,一切正常,但是代替“选项”,该函数返回[object Promise],而在控制台中则有适当的值。
以下是变量的示例(API响应类似):
var constructor = {
"element" : {
"data" : [
{
"type" : "section",
"id" : "id1",
"elements" : [
{
"type" : "input",
"subtype" : "text",
"label" : "Address",
"id" : "address",
},
{
"type" : "section",
"id" : "id2",
"elements" : [
{
"type" : "h3",
"text" : "Some text"
},
{
"type" : "select",
"label" : "Klient",
"id" : "id3",
"width" : 100,
"elements" : "source",
"source" : "source_path"
}
]
},
{
"type" : "section",
"id" : "id4",
"elements" : [
{
"type" : "h3",
"text" : "Some text 2"
}
]
}
]
}
]
}
}
这是代码:
async function getData(url = '') {
const response = await fetch(url, {
method: 'GET',
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'Content-Type': 'application/json'
}
});
return response.json();
}
const generateElements = (obj) => {
if(obj.type == 'input') doSomething();
if(obj.type == 'h3') doSomething();
if(obj.type == 'select'){
return `<select id="${obj.id}">
${
typeof obj.elements == 'object' ?
Array.isArray(obj.elements) &&
obj.elements.map((element) => {
return `<option id="${element}">${element}</option>`
}).join("")
: obj.elements == 'source' &&
getData(obj.source)
.then(data => {
data.map((element) => {
console.log(element.id, element.name)
return `<option id="${element.id}">
${element.name}
</option>`
}).join('')
})
}
</select>
<label for="${obj.id}">${obj.label}</label></div>`
}
if(obj.type == 'section'){
return `<section id="${obj.id}">
${ obj.hasOwnProperty('elements') &&
obj.elements.map((element) => {
return generateElements(element)
}).join('')
}
</section>`
}
}
getData('the_url2')
.then(data => {
data.map((element) => {
element.elementToAppend &&
jQuery(element.elementToAppend).append(generateElements(JSON.parse(element.data)))
})
});
constructor.map((element) => {
jQuery(element.elementToAppend).append(generateElements(JSON.parse(element.data)))
})
我试图将generateElements函数更改为async,但随后代码生成了[object Promise]来代替各节。我的另一个想法是等待API调用,但出现“等待仅在异步函数中有效”错误。当我将API调用从select分配给const并返回值时,它会在控制台中生成正确的html代码,但在函数结果中仍会显示[object Promise]。我还尝试了许多其他解决方案,但没有成功。
我不知道如何进行此操作,但是我无法更改API响应。 Qualtrics限制我使用框架和库。
编辑: 感谢@Bergi的支持,我得以解决我的问题。所以:
我将异步用于generateElements:
const generateElements = async (obj) => { ... }
等待获取功能:
await getData(obj.source)
.then(data => {
data.map((element) => {
console.log(element.id, element.name)
return `<option id="${element.id}">
${element.name}
</option>`
}).join('')
})
并保证递归:
( await Promise.all(obj.elements.map(async (element) => {
return await generateElements(element)
})
) ).join('')
再次感谢@Bergi! :)
答案 0 :(得分:-1)
如果您要获取API响应数据而不是承诺,则可能需要 await
response.json()
。
async function getData(url = '') {
const response = await fetch(url, { /* ... */ });
// return response.json();
return await response.json();
}
正如@bergi指出的那样,您的generateElements
函数也需要异步。
typeof obj.elements == 'object' ?
Array.isArray(obj.elements) &&
obj.elements.map((element) => {
return `<option id="${element}">${element}</option>`
}).join("")
: obj.elements == 'source' &&
(await getData(obj.source)) // ** await here
.map((element) => {
console.log(element.id, element.name)
return `<option id="${element.id}">
${element.name}
</option>`
})
.join('')