Promise 不会 return 有效值

Promise wont return valid value

我做了这个测试只是为了检查 API,但后来我尝试从第二次提取中添加一个 URL,使用在第一次提取中获得的值作为参数,然后 return 要在第一个 fecth 中添加的值。这个想法是将图像 URL 添加到 link。提前致谢。

function script() {
    const url = 'https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20'

    const result = fetch(url)
    .then( (res)=>{
        if(res.ok) {
            return res.json()
        } else {
            console.log("Error!!")
        }
    }).then( data => {
        console.log(data)

        const main = document.getElementById('main');

        main.innerHTML=`<p><a href='${data.next}'>Next</a></p>`;

        for(let i=0; i<data.results.length;i++){
            main.innerHTML=main.innerHTML+`<p><a href=${getImageURL(data.results[i].url)}>${data.results[i].name}</a></p>`;
        }

    })
}

 async function getImageURL(imgUrl) {
   
    const resultImg = await fetch(imgUrl)
        .then( (res)=> {
            return res.json()
        })
        .then (data => {
            console.log(data.sprites.other.dream_world.front_default);            
        })    
    return resultImg.sprites.other.dream_world.front_default;
}
    

一般来说,不要将 .then/.catch 处理程序与 async/await 混合使用。通常没有必要,它会像这样把你绊倒。

问题是您的履行处理程序(.then 回调)没有 return 任何东西,因此它创建的承诺由 undefined 履行。

你可以 return data,但实际上根本不使用 .then/.catch:

async function getImageURL(imgUrl) {
    const res = await fetch(imgUrl);
    if (!res.ok) {
        throw new Error(`HTTP error ${res.status}`);
    }
    const resultImg = await res.json();
    return resultImg.sprites.other.dream_world.front_default;
}

[注意我添加了 res.ok 的检查。这是(恕我直言)fetch API 中的一个 footgun,它不会拒绝其对 HTTP 错误(如 404 或 500)的承诺,仅在 网络 上错误。您必须明确检查 HTTP 错误。 (我把它写在我贫血的旧博客上 here。)]

还有一个问题,你使用 getImageURL:

// Incorrent
for (let i = 0; i < data.results.length; i++) {
    main.innerHTML=main.innerHTML+`<p><a href=${getImageURL(data.results[i].url)}>${data.results[i].name}</a></p>`;
}

这里的问题是 getImageURL,像所有 async 函数一样,return 是一个 承诺 。您正在尝试使用它,因为它 return 提供了您期望的履行价值,但它不能——它还没有那个价值。

相反,您需要等待您在该循环中创建的承诺得到履行。由于该循环是在同步代码中(不是 async 函数),我们将返回到 .then/.catch,并且因为我们想等待一组事情完成可以并行完成,我们会用 Promise.all:

// ...
const main = document.getElementById('main');
const html = `<p><a href='${data.next}'>Next</a></p>`;
Promise.all(data.results.map(async ({url, name}) => {
    const realUrl = await getImageURL(url);
    return `<p><a href=${realUrl}>${name}</a></p>`;
}))
.then(paragraphs => {
    html += paragraphs.join("");
    main.innerHTML = html;
})
.catch(error => {
    // ...handle/report error...
});

首先,您的

.then (data => {
            console.log(//...

在承诺链的末尾 returns 未定义。只需删除它,如果你想 console.log 它,请在 await.

之后的下一个 statement/next 行中执行 console.log(resultImg)

这是完成我的目标的最终版本。只是想留下这个以防万一有人发现它有用。感谢回答的人!

function script() {
    const url = 'https://pokeapi.co/api/v2/pokemon/?offset=20&limit=20'

    const result = fetch(url)
    .then( (res)=>{
        if(res.ok) {
            return res.json()
        } else {
            console.log("Error!!")
        }
    }).then( data => {
        console.log(data)

        const main = document.getElementById('main');

        main.innerHTML=`<p><a href='${data.next}'>Proxima Página</a></p>`;

        Promise.all(data.results.map(async ({url, name}) => {
            const realUrl = await getImageURL(url);
            return `<div><a href=${realUrl}>${name}</a></div>`;
        }))
        .then(paragraphs => {
            main.innerHTML=main.innerHTML+paragraphs;
        })
        .catch(error => {
            console.log(error);
        });
    })
}

 async function getImageURL(imgUrl) {
   
    const res = await fetch(imgUrl);

    if(!res.ok) {
        throw new Error(`HTTP Error ${res.status}`)
    } 
    
    const resultImg = await res.json();

    return resultImg.sprites.other.dream_world.front_default
}