Ionic V2 and Cordova Plugins - Uncaught TypeError:

2019-07-26 15:05发布

问题:

I am using Ionic v2 and the Phonegap Barcode Scanner plugin.

When executing the scanBarcode() function below I am getting the error:

Uncaught TypeError: Cannot set property 'test' of null

at

this.test = result.text;

code:

import {Page} from 'ionic-angular';


@Page({
  templateUrl: 'build/pages/scanBarcode/scanBarcode.html'
})
export class ScanBarcode {
  constructor() {
    this.test = "";
  }

  scanBarcode(){
    cordova.plugins.barcodeScanner.scan(
      function (result) {
        console.log(result.text);
        this.test = result.text;
        console.log("SB result" + test);
      },
      function (error) {
        alert("Scanning failed: " + error);
      }
    )
  }
}

The first console.log has no error and shows the correct information:

console.log(result.text);

回答1:

The problem with your code is that your are trying to access the 'this' pointer of your class inside the result function of the scan method.

In order to fix this, do the following:

scanBarcode(){

  //Create 'self' variable outside the scan function, assigning 'this' to it
  let self = this;

  cordova.plugins.barcodeScanner.scan(
    function (result) {
      console.log(result.text);
      //Use 'self' instead of 'this' to access 'test'
      self.test = result.text;
      console.log("SB result" + test);
    },
    function (error) {
      alert("Scanning failed: " + error);
    }
  )
}

Explanation

When you call the .scan() function, you give it two callbacks. You cannot use 'this' to accomplish what you want because in Javascript, 'this' has the context of the function caller.

Usually, when you access 'this' inside a callback, it has the 'window' context. That's because when you (define and) call a function without a object context, you are actually using the 'window' context. Example:

function fun(){ console.log('this = window; in here');
fun();

What actually happening is:

window.fun = function() { /* ... */ }
window.fun(); 

(For more information on this, read about javascript's prototype based object orientation model)

In this scenario you would have a Cannot set property 'test' of undefined error. But, since your callback is being called directly by the cordova plugin, I believe that 'this' has no context at all (I'm not sure, though).

Anyway, since the callback is not being called with your class instance context, 'this' does not represent a instance of your class and therefore does not have a 'test' property.

Finally, since a callback is a closure, and a closure remembers the environment in which it was created, the callback knows about the existence of the 'self' variable. That's why you can use it in this case.