簡體   English   中英

TypeError:無法讀取未定義的屬性(讀取“模型”)

[英]TypeError: Cannot read properties of undefined (reading 'model')

我是 Javascript 和 Typescript 的新手,我正在開發一個 electron 應用程序作為輔助項目。 我收到此錯誤,它可能與 function scope 有關,但我似乎不明白。 有人可以向我解釋這種行為並就如何處理這個問題給我一個建議嗎? 這是我的模塊文件:

主要.ts:

 /*
* Implementation of main module.
*/

import { app, BrowserWindow, ipcMain, dialog } from 'electron';
import path from 'path';
import Controller from './controller/controller';
import Model from './model/model';

class Main {
  controller: Controller;
  mainWindow: BrowserWindow | undefined;
  application: Electron.App;

  constructor(application: Electron.App, controller: Controller) {
    this.controller = controller;
    this.application = application;
  }

  openMessageBox(_event: Event, message: string) {
    const options = {
      title: 'Unable to start scanning',
      message,
    };
    if (!this.mainWindow) {
      return;
    }
    dialog.showMessageBox(this.mainWindow, options);
  }

  addHandlers() {
    ipcMain.handle('getNetworkInterfaceControllers', this.controller.getNetworkInterfaceControllers);
    ipcMain.handle('setInterfaceSelection', this.controller.setInterfaceSelection);
    ipcMain.handle('setInterfaceMac', this.controller.setInterfaceMac);
    ipcMain.handle('setBandSelection', this.controller.setBandSelection);
    ipcMain.handle('startScanning', this.controller.model.scanAccessPoints);
    ipcMain.handle('getAccessPoints', this.controller.getAccessPoints);
    ipcMain.handle('openMessageBox', this.openMessageBox);
  }

  createWindow() {
    this.mainWindow = new BrowserWindow(
      {
        width: 800,
        height: 600,
        webPreferences: {
          nodeIntegration: true,
          preload: path.join(__dirname, 'preload.js'),
        },
        darkTheme: true,
        icon: 'public/wlan-signal.png',
      })
    this.mainWindow.loadFile('public/main.html');
    this.mainWindow.on('closed', () => {
      this.controller.model.reset();
      this.application.quit();
    });
  }

  initialize() {
    this.application.whenReady().then(() => {
      this.createWindow();
      this.addHandlers();
    });
    this.application.on('activate', () => {
      if (BrowserWindow.getAllWindows().length === 0) {
        this.createWindow();
      }
    });
    this.application.on('window-all-closed', () => {
      if (process.platform !== 'darwin') {
        this.application.quit();
      }
    });
  }
}

const model: Model = new Model();
const controller: Controller = new Controller(model);
const main: Main = new Main(app, controller);
main.initialize();

Controller.ts:

/*
* Module implementing the controller.
*/

import Utils from '../utils';
import Model from '../model/model';

class Controller {
  model: Model;

  constructor(model: Model) {
    this.model = model;
  }

  public getNetworkInterfaceControllers() {
    this.model.scanNetworkInterfaceControllers();
    return Object.keys(this.model.networkInterfaceControllers);
  }

  public getAccessPoints() {
    this.model.stopScanningAccessPoints();
    return Object.keys(this.model.accessPoints);
  }

  public setInterfaceSelection(_event: Event, iface: string) {
    this.model.usedNetworkInterfaceController = this.model.networkInterfaceControllers[iface];
  }

  public setInterfaceMac(_event: Event, randomized: boolean) {
    this.model.macRandomized = randomized;
    if (this.model.macRandomized) {
      if (this.model.usedNetworkInterfaceController.changedMac) {
        return;
      }
      const randomMac = Utils.getRandomMac();
      this.model.usedNetworkInterfaceController.changeMac(randomMac);
    } else {
      this.model.usedNetworkInterfaceController.resetMac();
    }
  }

  public setBandSelection(_event: Event, bandValues: string []) {
    this.model.bandFlags = bandValues;
  }
}

export default Controller;

Model.ts:

/*
* Implementation of data model.
*/

import os from 'os';
import { ChildProcess, spawn } from 'child_process';
import NetworkInterfaceController from './networkInterfaceController';
import Utils from '../utils';
import AccessPoint from './accessPoint';

const CAPTURED_WAPS = './capturedwaps/capturedWAPS';
const CSV_PREFIX = '-01.csv';

class Model {
  networkInterfaceControllers: NetworkInterfaceController[];
  accessPoints: AccessPoint[];
  usedNetworkInterfaceController!: NetworkInterfaceController;
  macRandomized: boolean;
  bandFlags: string[];
  scanProcess!: ChildProcess;

  constructor() {
    this.networkInterfaceControllers = [];
    this.accessPoints = [];
    this.usedNetworkInterfaceController;
    this.macRandomized = false;
    this.bandFlags = [];
    this.scanProcess;
  }

  public scanNetworkInterfaceControllers() {
    const interfaces: NodeJS.Dict<os.NetworkInterfaceInfo[]> = os.networkInterfaces();
    this.networkInterfaceControllers = [];
    for (const [address, iface] of Object.entries(interfaces)) {
      if (!iface) {
        return;
      }
      if (address === 'lo' || address === 'eth0') {
        continue;
      }
      for (let i = 0; i < iface.length; i += 1) {
        if (iface[i].family === 'IPv4' && iface[i].internal === false) {
          const nic = new NetworkInterfaceController(iface[i], address);
          this.networkInterfaceControllers[address] = nic;
        }
      }
    }
  }

  public async scanAccessPoints() {
    this.scanProcess = spawn('sudo', ['airodump-ng', '--band', this.bandFlags.join(''), '-w',
      CAPTURED_WAPS, '--write-interval', '1', '--output-format', 'csv', this.usedNetworkInterfaceController.name]);
  }

  public async stopScanningAccessPoints() {
    this.scanProcess.kill('SIGINT');
    Utils.deleteClientsFromCsv(CAPTURED_WAPS + CSV_PREFIX);
    this.accessPoints = await Utils.readAccessPointsFromCsv(CAPTURED_WAPS + CSV_PREFIX);
  }

  public reset() {
    for (let i = 0; i < this.networkInterfaceControllers.length; i += 1) {
      this.networkInterfaceControllers[i].resetMac();
    }
  }
}

export default Model;

預載.ts:

/*
* Preload file that exposes APIs for the backend communication.
*/

import { contextBridge, ipcRenderer } from 'electron';

contextBridge.exposeInMainWorld('API', {
  getNetworkInterfaceControllers: () => ipcRenderer.invoke('getNetworkInterfaceControllers'),
  updateInterfaceSelection: (iface: string) => ipcRenderer.invoke('setInterfaceSelection', iface),
  updateInterfaceMac: (randomized: boolean) => ipcRenderer.invoke('setInterfaceMac', randomized),
  updateBandSelection: (bandValues: string[]) => ipcRenderer.invoke('setBandSelection', bandValues),
  startScanning: () => ipcRenderer.invoke('startScanning'),
  getAccessPoints: () => ipcRenderer.invoke('getAccessPoints'),
});

contextBridge.exposeInMainWorld('MSG', {
  openMessageBox: (message: string) => ipcRenderer.invoke('openMessageBox', message),
});

當我加載我的應用程序時發生錯誤:

Error occurred in handler for 'getNetworkInterfaceControllers': TypeError: Cannot read properties of undefined (reading 'model')
    at Controller.getNetworkInterfaceControllers (/home/dave/Schreibtisch/WiFi-Deauthenticator/build/controller/controller.js:15:14)
    at node:electron/js2c/browser_init:189:579
    at EventEmitter.<anonymous> (node:electron/js2c/browser_init:161:11327)
    at EventEmitter.emit (node:events:527:28)
Error occurred in handler for 'setBandSelection': TypeError: Cannot read properties of undefined (reading 'model')
    at Controller.setBandSelection (/home/dave/Schreibtisch/WiFi-Deauthenticator/build/controller/controller.js:39:14)
    at node:electron/js2c/browser_init:189:579
    at EventEmitter.<anonymous> (node:electron/js2c/browser_init:161:11327)
    at EventEmitter.emit (node:events:527:28)

現在我知道這已經經常解決了,但我就是無法理解我的特殊情況。

正如我所說,我是 Javascript 的新手,老實說,答案相當簡單。 我不得不將我的常規函數更改為箭頭函數,因為常規函數有自己的 this:

https://betterprogramming.pub/difference-between-regular-functions-and-arrow-functions-f65639aba256?gi=29d77c88a350

這樣我就可以從我的函數內部訪問我的 model。 用正確的“這個”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM