Javascript承诺和控制台日志?

时间:2020-04-20 06:28:49

标签: javascript promise async-await puppeteer

我需要有关Javascript承诺的帮助。

buttons-是一个NodeList。我从puppeteerAPI)那里得到的。
我需要带有特定文本的按钮列表。
我将buttons转换为实际按钮数组(page.evaluate API link):

  • 我通过数组进行映射,
  • 将其转换为按钮,
  • 检查文本,如果不是我所需要的,请return null
  • console.log按钮文字-它向我显示了我需要的文字-一切都很好。
  • 然后我增加counter
  • 并返回转换后的按钮。

之后,我过滤数组-检查是否为非null元素。 我希望goodButtons仅包含我需要的按钮-带有正确的文本。

但是输出是

buttons 328
button: Confirm
button: Confirm
... 100 lines of "good button text" in total
button: Confirm
counter 0
good buttons 328

所以计数器不会一次增加(或者有async / await的东西和我缺少的console.log的窍门?)
但是,尽管我登录控制台的按钮文本似乎是正确的,但是goodButtons数组似乎以某种方式包含了所有按钮。

代码

const buttons = await page.$$('button[type="button"]')
console.log('buttons', await buttons.length)

let counter = 0;
let goodButtons = await buttons.map(async button => {
    const btnText = await page.evaluate(btn => btn.innerText, button);

    if (!['Confirm'].includes(btnText)) return null

    counter++
    console.log('button: ', btnText)

    return await button
}).filter(button => button !== null)

console.log('counter', counter)
console.log('good buttons', await goodButtons.length)

UPD (在Felix Kling评论之后)

let counter = 0;
let goodButtons = buttons.map(async button => {
        const btnText = await page.evaluate(btn => btn.innerText, button);

        if (!['Confirm', 'Подтвердить'].includes(btnText)) return null

        counter++

        return await button
})
goodButtons = await Promise.all(goodButtons)
goodButtons = goodButtons.filter(button => button !== null)

输出

buttons 328
counter 149
good buttons 328

2 个答案:

答案 0 :(得分:1)

这是@Felix Kling的评论和@Ufuk的提示后的工作代码。

谢谢你们!

let counter = 0;
let goodButtons = buttons.map(async button => {
        const btnText = await page.evaluate(btn => btn.innerText, button);

        if (!['Confirm', 'Подтвердить'].includes(btnText)) return null

        counter++

        return await button
})
goodButtons = await Promise.all(goodButtons)
goodButtons = goodButtons.filter(button => button !== null)

输出

buttons 328
counter 149
good buttons 149

答案 1 :(得分:1)

async函数返回承诺。

因此,buttons.map( async function)返回一个诺言数组,其中一些已通过null来实现(通过从map函数返回null),而所有其他的诺言则通过返回来实现提供给map函数的button元素句柄。

您可以使用Promise.all将promise数组转换为可以从其中过滤null值的数组:

let counter = 0;

let goodButtons =  (await Promise.all(
    buttons.map(async button => {
        const btnText = await page.evaluate(btn => btn.innerText, button);

        if (!['Confirm', 'Подтвердить'].includes(btnText)) return null

        counter++
        return button
   }))
   .filter(button => button !== null)

请注意,数组的length属性是一个数字,因此无需await

类似地,在伪造的elementHandle对象中button,如果我已正确阅读文档,也不是一个保证,因此也不应该在await之前也需要await Promise.all(....

(编辑:感谢AndrewP。-必须将过滤器函数应用于数组 由<App> <location id="1" /> <location id="2" /> <Location id="3"> <User loactionId="3"> </User> </Location id="4"> </App> 返回)