electron app crashed when I import a file

Viewed 450

SOLUTION (although I would still LOVE an explanation)

if I include the interface code directly (without import) at the TOP of the preload.ts file everything works fine. I can cast to objects like I expected.


I have an electron app compiled to typescript. I have a main.ts and a preload.ts as shown in the starter example here. When I import a files into the preload.ts the app crashes right where the import is used. What am I doing wrong here?

The error says:

api is not defined

which is completely incorrect because the code works perfectly if the CandleRes import is removed at the marked lines below.

After some testing I found that:

  • The import statement itself doesn't seem to cause problems. When I remove the import and put the interfaces directly in the file I still get the same error

  • When I include the interface by copying and pasting in the preload.ts file (at the bottom) the file crashes whether or not I make any reference to the interface

main.ts

import { app, BrowserWindow } from "electron";
import * as path from "path";

let mainWindow: Electron.BrowserWindow;

function createWindow() {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, "preload.js")
    },
    width: 800
  });

  // and load the index.html of the app.
  mainWindow.loadFile(path.join(__dirname, "../index.html"));

}

app.on("ready", createWindow);

app.on("activate", () => {
  // On OS X it"s common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (mainWindow === null) {
    createWindow();
  }
});

preload.ts

import { CandleRes } from "./models"; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<THIS LINE CAUSES CRASH
let api: any;

// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.

window.addEventListener("DOMContentLoaded", async () => {
  replaceText("colnames", "Loading data...."); //<<<<<<<<<<THIS FIRES CORRECTLY
  setupApi(); //Omitted to save space. This inits the var api
  await getDataAsync();
});

async function getDataAsync() {
  try {
    let candles: CandleRes = ( //<<<<<<<<<<<<<<<<<<<<<<<<<<<<I attempt to use import here. App crashes
      await this.api.getCandles("USD_CAD", {
        granularity: "M5",
        count: 1
      })
    ).data;
    replaceText("currencies", candles + " string: " + JSON.stringify(candles));
  } catch (e) {
    replaceText("currencies", "currencies ERR: " + e);
  }
}
const replaceText = (selector: string, text: string) => {
  const element = document.getElementById(selector);
  if (element) {
    element.innerText = selector + ":" + text;
  }
};
function setupApi() {
  var key = "xxxxxxxxxxxxxxxxxxxxxxx"; //https://www.oanda.com/demo-account/tpa/personal_token
  var acctid = "xxx-xxx-xxx-xxx"; //https://www.oanda.com/demo-account/funding
  const Oanda = require("oanda-node-api");

  const config = {
    env: "fxPractice",
    auth: `Bearer ${key}`,
    accountID: acctid,
    dateFormat: "RFC3339"
  };

  this.api = Object.create(Oanda);
  this.api.init(config);
}

models.ts

export interface OHLC {
  o: string; // "1.34288"
  h: string; //"1.34336"
  l: string; //1.34278"
  c: string; //1.34315"
}

export interface Candle {
  complete: boolean; //true
  volume: number; //283
  time: string; //2020-02-28T17:50:00.000000000Z
  mid: OHLC;
}

//{"instrument":"USD_CAD","granularity":"M5",
//"candles":[
//{"complete":true,"volume":90,"time":"2020-02-28T21:55:00.000000000Z",
//"mid":{"o":"1.33974","h":"1.33974","l":"1.33932","c":"1.33968"}}]}
export interface CandleRes {
  instrument: string; //ex: "USD_CAD"
  granularity: string; //ex "M5"
  candles: Candle[];
}
1 Answers

You api variable is declared in the global scope, and you are trying to access it inside of functions using this.api which is incorrect. Just look at how the electron example uses mainWindow in your main.ts.

You do this once in getDataAsync() and twice in setupApi(). Change all your this.api to just api and this particular problem should be gone.

If you want to expand knowledge in this area, here is an excellent article: 'this' in TypeScript

Related