Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
195 views
in Technique[技术] by (71.8m points)

javascript - How to use async function with set interval

async function getContent(){
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(url);
    const content =  await page.content();
    await console.log(content);
    await browser.close();
}

setInterval(searchTarget(), 13000);

I have this async function that gets content from a webpage using puppeteer. I want to be able to check the web page every so often, so I tried to use setinterval but I kept getting errors. Any ideas?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)
  • You've posted the definition of getContent, not searchTarget.
  • You're passing the result of searchTarget to setInterval rather than passing a reference to the function searchTarget.
  • You say you're getting errors but haven't said what those errors are.
  • You can use an async function with setInterval.
  • You don't need to use await with console.log (you shouldn't use await because as console.log doesn't return anything, let alone a Promise<T>).

I assume what you actually want is this:

async function getContent() {
    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(url);
    const content =  await page.content();
    console.log(content);
    await browser.close();
}

const timerId = window.setInterval( getContent, 13 * 1000 );

// You can call `window.clearInterval( timerId )` to stop the interval loop.

I recommend adding error-handling that stops the interval loop on the first error:

/** @type {number} */
let intervalTimerId = null;

async function getContent() {
    try {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        await page.goto(url);
        const content =  await page.content();
        await console.log(content);
        await browser.close();
    }
    catch( err ) {
        console.error( "Error in getContent: %o", err );
        if( intervalTimerId ) {
            window.clearInterval( intervalTimerId );
        }
    }
}

intervalTimerId = window.setInterval( getContent, 13 * 1000 );

Alternative approach:

As other users like @mplungjan and @RohanAsokan have pointed out, there are potential design issues with your code because setInterval will call getContent every 13 seconds even if the previous call to getContent still hasn't finished yet - this could happen if (for example) await page.content() took longer than 13 seconds to run.

In which case the solution is to use window.setTimeout instead of window.setInterval and to call it from within getContent, like so:

/** @type {number} */
let lastSetTimeoutId = null;

async function getContentAndStartLoop() {
    try {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        await page.goto(url);
        const content =  await page.content();
        console.log(content);
        await browser.close();

        lastSetTimeoutId = window.setTimeout( getContentAndStartLoop, 13 * 1000 );
    }
    catch( err ) {
        console.error( "Error in getContent: %o", err );
    }
}

Note that getContentAndStartLoop will resolve after the first loop but keep on running itself until an error is thrown.

Better approach:

I think it'd be better to structure it like so (using a Promise-adapter for setTimeout named delay):

async function myProgram() {
    
    const url     = "https://thispersondoesnotexist.com/":
    const browser = await puppeteer.launch();
    const page    = await browser.newPage();
    
    try {
        while( true ) {
        
            await page.goto( url );
        
            const content = await page.content();
            console.log( content );

            await delay( 13 * 1000 );
        }
    }
    catch( err ) {
        console.error( "Error in myProgram: %o", err );
    }
    finally {
        await browser.close();
    }
    
}

async function delay( ms, state = null ) {
    
    return new Promise( ( resolve, reject ) => {
        window.setTimeout( () => resolve( state ), ms );
    } );
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...