Can't work out how to use async / await methods in a GObject class

,

I’m trying to understand how to create and use asynchronous methods in GObject classes.

There’s lots of great examples on this in the “File operations” page of gjs.guide, but I can’t even get a basic async / await function working. Have spent 3 hours reading documentation, searching online, experimenting, and have had no luck, and am hoping someone can help me.

I’ve taken the example “Open file” code from Workbench and tried to add it to a GObject class.

When I run the following code via Builder, the file dialog opens. When I select a file, the dialog closes and then nothing else happens. The console only logs the name of the file I selected when I close the application window.

import GObject from 'gi://GObject';
import Gtk from 'gi://Gtk';
import Adw from 'gi://Adw';
import Gio from 'gi://Gio';

Gio._promisify(Gtk.FileDialog.prototype, "open", "open_finish");

export const Window = GObject.registerClass({
	GTypeName: 'AppWindow',
	Template: 'resource:///com/example/applicationId/ui/Window.ui',
}, class extends Adw.ApplicationWindow {
  constructor(params={}){
    super(params);
    this.openFile();
  }

  vfunc_close_request() {
    super.vfunc_close_request();		
    this.run_dispose();
  }


  async openFile() {
    const file_dialog = new Gtk.FileDialog();
    const file = await file_dialog.open(this, null);
    console.log("Selected file:", this.getFileName(file));
  }

  getFileName(file) {
    const info = file.query_info(
      "standard::name",
      Gio.FileQueryInfoFlags.NONE,
      null,
    );
    return info.get_name();
  }

});

The same thing happens with every other async method I’ve tried. The application will always get stuck on the “await” line and won’t proceed any further until the application is closed.

Am I putting everything in the right place?

Hey Chris,

use GApplication.runAsync instead of GApplication.run.
https://gjs-docs.gnome.org/gjs/overrides.md#gio-application-runasync

Do you remember where you go the initial application code example from? We should probably fix it.

This link works better doc/Overrides.md · master · GNOME / gjs · GitLab

This worked perfectly! Ahhhh, I could kiss you. Thank you!

For anyone else who arrives here, in main.js, I changed this:

export function main(argv) {
	return new Application({ 'application-id': pkg.name }).run(argv);
}

to this:


export function main(argv) {
	return new Application({ 'application-id': pkg.name }).runAsync(argv);
}

Yes, this page is where I first came across the asynchronous file operations:

I also tried following this guide, which uses the async methods:

Neither page mentions the runAsync command.

When I couldn’t get the examples from either of those to work, I found the “Save File” and “Load File” examples in Workbench. However, neither of those examples mentioned needing to use the runAsync command either unfortunately.

I created my project using the “GNOME Application” template in Builder, so perhaps it’s worth switching the method in main.js from run to runAsync by default there?

2 Likes

Yes, please do. I thought it already had that. Would you like to submit a merge request?

Sure thing, I’ll have a go at submitting a merge request

My mistake, it looks like Gnome Builder uses the runAsync command like you said.

I realise that the original source of this confusion was the GJS Book tutorial, specifically this page:

The tutorial asks you to set up the project in a slightly different way to the Gnome Builder template. I must have reused some code from that tutorial in the project that I started afterwards.

If it’s possible to change the command in that tutorial from .run to .runAsync then that might help other new developers from running into this issue. I’ll report an issue on the guide’s Gitlab page

Edit: Here’s the issue I created:

1 Like