javascript答应不等Promise.all

javascript Promise not wait Promise.all

因此 getAstronautsData 向 API 提出请求,然后 return 承诺数组。这承诺会向 Wiki API 发出请求并解析对象中的响应。然后 exampleAsyncFunc 必须等待所有的承诺和 return 一个包含所有关于宇航员信息的大对象。 但是如果我使用 Promise.all 函数结束并且控制台是清晰的。

function getAstronautsData() {
    return new Promise((resolve, reject) => {
        getData('http://api.open-notify.org/astros.json', "http", (data) => {
            resolve(data) // get Astronauts list from API
        })
    }).then((astronautsList) => {
        return astronautsList.people.map((person => // return array of promises 
            new Promise(resolve => {
                getWikiData(person.name, (data) => { // request on Wiki API
                    resolve({info: data.extract, img: data.thumbnail.source})
                })
            })
        ))
    })
}


async function exampleAsyncFunc (){
    let promisesList = await getAstronautsData()
    // next code just few variant was i try
    let data = await Promise.all(promisesList)// it's not working.
    console.log(data) 

    Promise.all(promisesList).then(data => console.log(data)) //it's not working. Function display nothing

    
    promisesList.forEach((promise) =>  { //it's working but not so elegant
        promise.then(data => console.log(data))
    })

}

exampleAsyncFunc ()

function getWikiData(searhTerm, callback) {
    getData(getUrlString(searhTerm), "https", (data) => {
        const regex = new RegExp(searhTerm.replaceAll(" ", ".*"));
        for (let page in data.query.pages) {
            if (data.query.pages[page].title === searhTerm || regex.test(data.query.pages[page].title)) {
                callback(data.query.pages[page])
                return
            }else{
                callback(null)
            }


        }

    })
}

您似乎正确地使用了 Promise.all,但是如果 中的任何 Promise.all 承诺被拒绝,那么总体 Promise.all 承诺将reject 也不会发生任何事情,在你的 forEach 版本中,它只会默默地跳过这些承诺并继续下一个条目。

同样,如果列表中的任何承诺仍处于未决状态:如果是这样,那么 Promise.all 承诺将永远不会解决。这可能是因为您有一长串 return 值并且整个列表需要比预期更长的时间来解决,或者因为您的 getWikiData 调用遇到错误而您没有通过在你的数组中拒绝那个特定的承诺。

您可以通过确保每次调用 then 后跟 .catch(console.error)(或更强大的错误处理程序)来调试此行为。

首先让我透露一下,我是一个很有希望的党派,坦率地说,我对回调表示遗憾。这里的含义是我不会用回调写你的getDatagetWikiData

我还要指出,我支持@t.niese 在评论中所说的:Because it does not make sense having both let data = await Promise.all(promisesList) and promisesList.forEach((promise) => {.

无论如何,您的代码不必要地复杂,可以像这样简化:

function getAstronautsData(callback) {
    getData('http://api.open-notify.org/astros.json', "http", data => {
        callback(data.people.map(person =>
            new Promise(resolve => {
                getWikiData(person.name, data => {
                    resolve(data);
                })
            }))
        )
    })
}

function exampleAsyncFunc (){
    getAstronautsData(promises => {
        Promise.all(promises)
            .then(result => {
                //result will contain those resolved promises
                console.log(result);
            })
    });
}

exampleAsyncFunc ()

请注意,我将回调传递给 getAstronautsData 并从该函数内部使用您最终想要解决的承诺数组调用它。如您所见,这里也不需要 async

好的,问题出在 API(在 API 中,一位宇航员的名字是 "Tom Marshburn",但在 Wiki 上,他的页面的标题是 "Thomas Marshburn")和功能 getWikiData 不是 return 任何关于错误的数据。所以我解决了这个问题。 谢谢大家的帮助!!!