Home > Enterprise >  Why fetch() does not exit in for loop?
Why fetch() does not exit in for loop?

Time:12-05

I use fetch() to print labels. There are some scenario when I need to loop through the data and print multiple labels. The printing it's working fine, but after the first loop the script stop running.

I use async function in order to slow down a printing.

async function printing() {

    for (let w = 0; w < print_labels.length; w  ) {
       
        const label = `data of the label`

        fetch('http://111.111.1.111:9100', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: label
        })
        
        console.log(`${w}. label printed.`)
        await sleep(2000);


    }
}; 
printing()

Ho can I cancel/stop the fetch() function? Or maybe any other solution how to use fetch() post in for loop?

CodePudding user response:

you can use the AbortController and AbortSignal objects. These objects provide a way to abort an ongoing fetch() call, allowing you to cancel the request and stop it from running.

// Create a new AbortController and AbortSignal
const controller = new AbortController();
const signal = controller.signal;

// Use the AbortSignal in the fetch() call
fetch('http://111.111.1.111:9100', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  },
  body: label,
  signal: signal
});

// Use the AbortController to cancel the fetch() call
controller.abort();

Another way is using for loop to stop the fetch() call after each iteration.

async function printing() {
  for (let w = 0; w < print_labels.length; w  ) {
    // Create a new AbortController and AbortSignal
    const controller = new AbortController();
    const signal = controller.signal;

    // Use the AbortSignal in the fetch() call
    fetch('http://111.111.1.111:9100', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: label,
      signal: signal
    });

    console.log(`${w}. label printed.`)
    await sleep(2000);

    // Use the AbortController to cancel the fetch() call
    controller.abort();
  }
}; 

printing()

CodePudding user response:

AbortController needs to be used to abort requests, as another answer mentions. Both failed and aborted fetch will throw errors, and errors need to be correctly handled in order to not cause exceptions.

Generally request promise needs to be awaited. In this case race can be used to handle both request and delay promises:

let controller = new AbortController();

try {
  await Promise.race([
    fetch(..., { ... , signal: controller.signal }),
    new Promise(resolve => {
      setTimeout(resolve);
      controller.abort();
    }, 2000);
  ]));
} catch (err) {
  console.error('Failed');
}

Aborted request causes an error that can be detected with err.name === 'AbortError' check and suppressed if necessary, but in this case this may not be needed because delay promise resolves first on timeout and makes Promise.race resolve with undefined with AbortError being suppressed.

  • Related