quagga2 icon indicating copy to clipboard operation
quagga2 copied to clipboard

Unhandled promise rejection: TypeError: Cannot read property 'attachData' of undefined

Open ricocynthia opened this issue 5 years ago • 8 comments

Hello!

As I run tests for my Angular app, I am encountering this error Unhandled promise rejection: TypeError: Cannot read property 'attachData' of undefined in components that aren't using the barcode scanner component I created using this library.

Here's an example of the error message I am seeing while I run the tests. This is an example where it's occurring in a component that isn't using the barcode scanner. image

Any suggestions on how to resolve this? Am I not catching a promise correctly somewhere?

ricocynthia avatar Oct 13 '20 15:10 ricocynthia

I'm not sure how to help you on that one -- according to the stack trace, someone is calling initializeCamera in your component, which goes to Quagga.start, which.. ends up calling into a frame_grabber that doesn't exist. I'd need to be able to get the parameters start() is being called with, to be able to figure out how you're getting an empty frameGrabber... but on top of that, I think the reason for this, overall, is that you're not expecting start() to be called here, and it is?

ericblade avatar Oct 13 '20 19:10 ericblade

@ricocynthia did you find anything further on this?

ericblade avatar Nov 13 '20 05:11 ericblade

@ericblade @ricocynthia any progress on this?

B0ngSter avatar Apr 01 '21 09:04 B0ngSter

Anyone able to make a minimal reproduction case so I can have a look at it? I know absolutely nothing about Angular. :|

ericblade avatar Apr 05 '21 06:04 ericblade

I have just been looking at this myself and got the same error, it happens if you call start() outside of the init() callback, if you make sure that start() is only called within the init() callback it works as expected, example code below

Angular Component

import {Component, ElementRef, OnInit} from '@angular/core';
import Quagga from "@ericblade/quagga2";

@Component({
  selector: 'app-search-form',
  templateUrl: './form.component.html',
  styleUrls: ['./form.component.scss']
})
export class FormComponent implements OnInit {
  query?: string;
  constructor(private elRef: ElementRef) { }
  ngOnInit(): void {
if (this.elRef.nativeElement.querySelector('#camera') !== null) {
    Quagga.init({
      inputStream: {
        name: 'live',
        type: 'LiveStream',
        target: this.elRef.nativeElement.querySelector('#camera'),
      },
      decoder: {
        readers: ['code_128_reader', 'ean_reader'],
      },
      locate: true,
    }, (err) => {
      if (err) {
        console.log(err);
        return;
      }
      console.log('Initialization finished, Ready to start');
      Quagga.start();
      Quagga.onDetected((val) => {
        console.log(val.codeResult.code)
      })
    })
  }
}
}

The HTML is simply just a div with an ID

<div id="camera"></div>

ghost avatar Aug 15 '21 20:08 ghost

That seems like a reasonable thing we should guard against, but does it match the OP, here? "in components that aren't using the barcode scanner component"?

i'm wondering if i start throwing there, would whatever OP's problem is become just a documented throw? like, this is where the error is occuring, but is it the root cause of what's happening?

ericblade avatar Aug 15 '21 23:08 ericblade

For root cause, Based on what I can see the error is being thrown because the Quagga code can't find the element it trying to attach to, which is the correct behaviour of the code and I'm not convinced that the issue lies with Quagga without actual code examples from the OP

Noting that this is only speculation, only thing I can think of which would cause what the OP is seeing is they start the camera and then the test moves on to other components of Angular, without more information from the OP not much I could comment on the exact nature of the error

But could be fixed of calling ngOnDestory() to stop() the camera when the component changes and the barcode scanner is no longer being used

  ngOnDestroy() {
    Quagga.stop();
  }

There could also be something in the OP's code is trying to restart the camera and could be a simple fix by adding some logic to check if the element exists if (this.elRef.nativeElement.querySelector('#camera') !== null) { ... }

Again some comments from the OP would help get to the root cause as I have not been able to replicate the issue other than calling start() outside of the init() callback

ghost avatar Aug 16 '21 08:08 ghost

right, like I'm curious why Angular is causing it to occur in different parts of the code. Even if it's being used correctly, is OP structuring something so that Angular would be calling init() and start() several times unexpectedly?

Either way, though, it sounds like it's probably a good idea to either make start() throw if init() hasn't been completed, and/or if start() receives a configuration block, then do init() and chain to start() when it's done...

ericblade avatar Aug 16 '21 11:08 ericblade