Search code examples
javascripthtmlqr-code

Why do these generate two separate outcome?


I created a my very first QR Code Scanner

my first version was like this

function decodeQRCode(photo) {
  const scanner = new BarcodeDetector({
    formats: ['qr_code']
  })
  scanner.detect(photo)
    .then((barcodes) => {
      bar_length = barcodes.length
      if (bar_length != 0) {
        barcodes.forEach(
          (barcode) =>
          input.setAttribute("value", barcode.rawValue),
        );

        input.addEventListener('input', form.submit())
        setTimeout(takepicture, 3000);
        console.log("success")

      } else {
        setTimeout(takepicture, 1500);
      }
    })
    .catch((err) => {
      console.error(err);
    });

my second version looks like this

function decodeQRCode(photo) {
  const scanner = new BarcodeDetector({
    formats: ['qr_code']
  })
  setTimeout(() => {
    scanner.detect(photo)
      .then((barcodes) => {
        bar_length = barcodes.length
        if (bar_length != 0) {
          barcodes.forEach(
            (barcode) =>
            input.setAttribute("value", barcode.rawValue)
          );

          input.addEventListener('input', form.submit())

        } else {
          takepicture()
        }
      })
      .catch((err) => {
        console.error(err);
      });
  }, 3000)

On my 1st version it is set to scan qrcodes every 3 seconds, because I set it to callfunction takepicture() with a 3 seconds delay but the console.log("success") continuously prints out "success" until I point the camera away from the QRCode

On my 2nd version, I still used setTimeout but with arrow function and it is doing the way I wanted it to do which is scan every 3 seconds

I just dont really know why it's continuously printing on my first version, both are set to call function takepicture() with a 3 seconds delay but just in a different approach


Solution

  • It's simple: setTimeout(takepicture, 3000); acts like an asynchronous function. That means, the code executes that line and then continues with the remainder of the code without waiting for what happens inside the function (which is waiting for 3 seconds and then calling takepicture).

    In your second version you have wrapped all the code inside the setTimeout function, which forces the code to wait for 3 seconds before executing that code.

    In other words:

    setTimeout(takepicture, 3000);
    console.log("success");
    

    will print "success" immediately, because the code does not wait for the setTimeout function to complete.

    But:

    setTimeout(() => {console.log("success");}, 3000);
    

    Will wait 3 seconds before printing "success".

    Because your first snippet executes the code every time a qr code is detected, and it does not wait for the set timeout function to complete, you will therefore continuously get success messages.

    For more information, see this article on Asynchronous Javascript.

    Hope that helps.