Console.log返回我需要的内容,但返回返回“ [object Promise]”字符串

时间:2020-05-12 14:02:27

标签: javascript json asynchronous promise async-await

我有两个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! :)

1 个答案:

答案 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('')