Author: With the day

Common applications include start, activate, and close events. Electron, as a cross-platform GUI framework, requires more events for different scenarios. To gain a deeper understanding of the Electron lifecycle, you need to have a clear understanding of the application lifecycle, window lifecycle, and page lifecycle timing.

A picture is worth a thousand words:

1. Event description of application startup and exit

These events are broken down into three parts: App events, BrowserWindow events, and Web events in the Renderer process. These are the sorting out of official documents and practical experience summary:

1. App event introduction

Events:will-finish-launching

Returns: event: event

And events in the Windows/Linux ready the same time, in the macOS equivalent to NSApplication applicationWillFinishLaunching notification, which is at the beginning of the NSApplication initialization, The default notification center initiates this event immediately, so it must precede the Ready event.

Purpose: Commonly used for open-file and open-URL listeners, and to enable crash reporting and automatic updates.

Events:ready

Return: event: event, launchInfo: Record
,>

Event: open-file [macOS]

Open-file should be listened on before ready. Event.preventdefault () if you take over the file’s opening

Triggering conditions:

  • Triggered when the application is already open and the file is opened by extension or by the open command on the macOS command line
  • Trigger when dragging and dropping a file to the Dock but the application is not yet running

On Windows computers, parsing is done through process.argv of the main process

Event: open-url [macOS]

Returns: event: event, URL: string

The open-URL event is triggered when the system opens the URL via Electron. If you want to take over opening the URL yourself, call event.preventDefault(). And to define the URL scheme in info.plist, if the Electron Builder package is available, you can find the extendInfo configuration and save a lot of trouble.

The exact words were: Your application’s Info.plist file must define the URL scheme within the CFBundleURLTypes key, and set NSPrincipalClass to AtomApplication.

// main.ts // for electron-test://abc? query1=value1 app.setAsDefaultProtocolClient('electron-test'); app.on('will-finish-launching', (event: Event) => { log(`==> app-event: will-finish-launching <===`); app.on('open-url', (event: Event, url: string) => { log(`==> app-event: open-url <===`, url); }); });Copy the code

After this is done, for example, type the electron-test:// ABC? Query1 =value1 Address will open Electron and open-URL will capture the path information.

Event: Activate [macOS]

Return: event: event, hasVisibleWindows: Boolean

The event activate only reactivates the application when it is first started, when the application is already running, or when the application’s dock or taskbar icon is clicked. If Cmd+Tab is used, this function will not be activated. In this case, did-become-active is required.

The re-open procedure here is that macOS defaults to applying singleton mode. If you try to run another instance, activate the already running instance.

Events:did-become-active

Returns: event: event

The did-BE-active event is triggered when switching to the application, such as an application without a window or the first time the application is started.

Events:session-created

Returns: session: session

Create a default session, often used to isolate network request environments.

Events:web-contents-created

Returns: Event event, window: BrowserWindow

The context for creating webContents is ready. It may be initialized more than once

Events: a browser window — created

Returns: Event: event, window: BrowserWindow

A window is created using session-created, web-contents-created, and browser-window-created. But I don’t know why after the app Ready event, the event web-contents-created is triggered.

Events: the second instance

Returns: event: event, argv: string[], workingDirectory: string

In most cases the application is in the macOS singleton pattern, when the restart, if the call. The app requestSingleInstanceLock () will be in the original operation, the application of trigger this event, whether new application can control the exit.

Events:window-all-closed

Return: **** none

Quit, CMD + Q, or menu exit, or any other way to exit the software.

This event is not listened on by default. Closing all Windows automatically exits the application. Once this event is heard, all Windows will not exit the application after closing, requiring the developer to control.

Events:before-quit

Returns: event: event

Interrupt: Yes

Any routine attempt to shut down the application is triggered immediately. Electron document said autoUpdater. QuitAndInstall () will close all the Windows, and then call the app. The quit ().

Events:will-quit

Returns: event: event

Interrupt: Yes

If window-all-closed is not listened on, will-quit is triggered after all Windows are closed. If window-all-closed is monitored, will-quit is triggered and window-all-closed is not triggered.

Events:quit

Returns: event: event, exitCode: number

On Windows, the before-quit and quit events are not triggered if the application is shut down due to a system shutdown/restart or user logout.

2. BrowserWindow event introduction

Events: the close

Returns: event: event

This precedes the BEFOREUnload and beforeunload of DOM events on the Web, which in general handle window closing via beforeUNLOAD:

window.onbeforeunload = (e) => {
  console.log('I do not want to be closed')
  e.returnValue = false // equivalent to `return false` but not recommended
}
Copy the code

Events:closed

Returns: no

Because this is an asynchronous event, the callback method does not affect the BrowserWindow lifecycle.

Events: ready – to – show

Returns: no

This window property, if it is show:true, will also trigger the event if it is not displayed.

3. Web events in the Renderer process

Event: Window: load

Returns: event: event

Triggered when a window starts loading, there are two ways to add listening, as well as unlaod and beforeunload below:

window.onload = (event: Event) => {
  console.log(event.type) // output: load
}
window.addEventListener('load', (event: Event) => {
  console.log(event.type) // output: load
})
Copy the code

Event: Window: unload

Returns: event: event

Unload events are not interrupted.

Normally, the Electron exit does not have time to issue an UNLOAD event, only close and reload Windows do.

Event: window: beforeunload

Returns: event: event

Interrupt: Yes

Returning non-undefined will break the main process BrowserWindow’s close event will also be triggered when the window is reloaded

Event: Document: DOMContentLoaded

Returns: event: event

Trigger when all DOM is ready.

Exit scenario

1. Exit normally

  • Cmd+qOr the exit button in the menu, in WindowsAlt+F4
  • app.quit()
  • autoupdater.quitAndInstall()
  • app.reluanch()

2. Exit abnormally

Such as the common call to process.crash() in the main process.

3. The SIG signal exits

The most common way to exit software from the command line is Ctrl+ C, and the command line sends a SIGKILL signal to the process. There are other common ways to stop a process, such as kill -s kill 24567 or kill -9 24567:

1       HUP (hang up)
2       INT (interrupt)
3       QUIT (quit)
6       ABRT (abort)
9       KILL (non-catchable, non-ignorable kill)
14      ALRM (alarm clock)
15      TERM (software termination signal)
Copy the code

4. Specific exit examples

Run Cmd+q to exit the cli

==> app-event: will-finish-launching <===
==> app-event: session-created <===
==> app-event: web-contents-created <===
==> app-event: browser-window-created <===
==> app-event: ready <===
==> app-event: did-become-active <===
==> app-event: web-contents-created <===
==> html-event: DOMContentLoaded <===
==> html-event: load <===
==> window-event: ready-to-show <===
==> app-event: before-quit <===
==> window-event: close <===
==> html-event: beforeunload <===
==> app-event: will-quit <===
==> app-event: quit <===
==> window-event: closed <===
Copy the code

==> window-event: closed <=== = this event is sent last because Closed is completely asynchronous and does not matter once it is triggered. Using app.reluanch() does not trigger an unload event as does CMD +q.

Start normally, press CTRL + C to exit

. ==> window-event: ready-to-show <=== ^C==> app-event: before-quit <===Copy the code

After startup, all events are normal, but after quitting the application is interrupted by CTRL + C, Electron emits only before-quit events. Try something else:

  • SIGHUP is roughly consistent with the normal exit process

  • SIGINT is the signal given by CTRL + C

  • SIGQUIT causes the entire application to quit with no response at all

  • SIGABRT is the same as above

  • SIGKILL effect is the same as above

  • SIGSEGV has the same effect as above and is also the signal sent by process.crash()

  • SIGTERM is the same as the normal exit process and is also the exit method of app.quit()

Start normally and exit via app.exit()

Exiting in this way, as with process.exit(), only triggers the quit event.

==> html-event: DOMContentLoaded <===
==> window-event: ready-to-show <===
==> app-event: quit 0 <===
Copy the code

Start normally, exit with beforeUnload interrupt

Interrupt application exit and window closing by calling Event. returnValue = false in beforeUnload:

window.onbeforeunload = (event: Event) => {
  log('beforeunload')
  event.returnValue = true
}
Copy the code

The following three events are repeatedly called through CMD +q:

==> app-event: before-quit <===
==> window-event: close <===
==> html-event: beforeunload <===
Copy the code

Close the window directly:

==> window-event: close <===
==> html-event: beforeunload <===
Copy the code

Normal startup, interrupted by the BrowserWindow Close event, will only trigger the close event:

==> window-event: close <===
==> window-event: close <===
==> window-event: close <===
Copy the code

BrowserWindow Closed events do not have events.

If the startup is normal, run app before-quit and press CMD +q, the window will not be closed.

==> app-event: before-quit <===
==> app-event: before-quit <===
==> app-event: before-quit <===
Copy the code

Closing by Ctrl+ C or some SIG signal above will ignore the interrupt closing operation.

Normal startup, interrupted by app will-quit, directly press CMD + Q will close all Windows, but the program is still active.

==> app-event: before-quit <===
==> app-event: will-quit <===
==> app-event: before-quit <===
==> app-event: will-quit <===
==> app-event: before-quit <===
==> app-event: will-quit <===
Copy the code

Closing by Ctrl+C or some SIG signal above will ignore the interrupt closing operation.

To sum up, it can be summarized as a figure:

3. Startup scenario

There are many common startup methods for software, such as open or Start in Windows, URL scheme and system startup, or dragging a document to the Dock or tray to start. Let’s talk about the path of the software parameters and environment after starting the software.

1. Common startup

Generally, double-click the software to launch, and after will-finish-launching and Ready, enter the app screen as normal.

2. The application is started in singleton mode

In application startup, test app. RequestSingleInstanceLock () is a singleton pattern, if it is out, and send an event to the second instance, from here and then get out of the application of the argv and CWD.

The way to check for a singleton is to see if there is a lock file under app.getPath(‘userData’).

3. Start the system on the CLI

The command line /path/to/app –arg1 value1 –arg2 value2 document/path will pass process.argv and process. CWD when the application starts

4. Start the vm using the URL scheme

Through the app. SetAsDefaultProtocolClient (‘ electron – test) registered url scheme, and then open in app events – url url parameter for url information:

==> app-event: did-become-active <=== ==> app-event: open-url <=== electron-test://happy? abc=eee#ii=aaCopy the code

5. Start by dragging it to the Dock or tray

The supported file types need to be declared in info.plist. For example, electronBuilder can register supported CFBundleDocumentTypes in extendInfo field. The event open-file is triggered.

Four, other

Q: Why was web-contents-created triggered twice in the previous experiment?

A: because the source code invokes the mainWindow. WebContents. OpenDevTools () opened the DevTools, so will be another new loading DevTools webContents environment. Even if a separate DevTools window pops up, a WebContents is created.

And on Windows, web-contents-created doesn’t fire twice, but ready-to-show does.

Q: In Windows, before-quit, will-quit, and quit events are not triggered when the user shuts down, restarts the system, or logs out of the current user. How do I handle the task when I exit?

A: If you must, you need to introduce A third-party library, such as edge.js. It is usually best to do some temporary storage of the exit scene so that when it is opened again, it can be processed later.

Q: What happens when BrowserWindow instances call browserWindow.destroy()?

A: Only closed events are notified. Other events such as CLOSE of UNLOAD, beforeUnload, and BrowserWindow are not triggered.

The code examples used in this article are here github.com/yantze/elec… .

Last but not least, please pay attention to our public account.