Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/427.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在GJS执行一系列异步任务之后,我如何安排事情发生?_Javascript_Asynchronous_Gtk_Gio_Gjs - Fatal编程技术网

Javascript 在GJS执行一系列异步任务之后,我如何安排事情发生?

Javascript 在GJS执行一系列异步任务之后,我如何安排事情发生?,javascript,asynchronous,gtk,gio,gjs,Javascript,Asynchronous,Gtk,Gio,Gjs,我正在使用GJS和GNOME平台用JavaScript编写一个简单的桌面应用程序:GTK+、GLib、Gio、GObject。下面的代码说明了我面临的情况,并且更容易复制,因为它不需要访问应用程序使用的文件。简而言之,我希望在完成一系列异步任务(加载一系列文件的内容)后运行指定的代码行。我如何在GJS中做到这一点,最好使用来自Gio或JavaScript本身的东西 #/usr/bin/gjs const Lang=imports.Lang; const Gio=imports.gi.Gio;

我正在使用GJS和GNOME平台用JavaScript编写一个简单的桌面应用程序:GTK+、GLib、Gio、GObject。下面的代码说明了我面临的情况,并且更容易复制,因为它不需要访问应用程序使用的文件。简而言之,我希望在完成一系列异步任务(加载一系列文件的内容)后运行指定的代码行。我如何在GJS中做到这一点,最好使用来自Gio或JavaScript本身的东西

#/usr/bin/gjs
const Lang=imports.Lang;
const Gio=imports.gi.Gio;
const GLib=imports.gi.GLib;
const GObject=imports.gi.GObject;
const Gtk=imports.gi.Gtk;
const Home=新语言类({
姓名:“家”,
//开始代码段1
_enumerateChildrenAsyncCallback:函数(dir,result){
让fileEnumerator=dir.enumerate\u children\u finish(结果);
让显示名称、文件、文件信息、文件类型、iter;
while((fileInfo=fileEnumerator.next_file(null))){
iter=this.model.append();
displayName=fileInfo.get_display_name();
这个.model.set(iter[0],[displayName],1);
file=dir.get_child(fileInfo.get_name());
fileType=file.query\u file\u type(Gio.FileQueryInfoFlags.NONE,null);
如果(fileType!=Gio.fileType.REGULAR)继续;
加载内容异步(空,函数(文件,结果){
让[success,contents,etag]=file.load\u contents\u finish(结果);
让消息=”;
如果(成功){
message=“已完成加载文件%s”;
}否则{
message=“无法加载文件%s”;
}
日志(message.replace(“%s”,file.get_basename());
});
}
},
_init:function(){
this.application=新的Gtk.application();
this.application.connect(“activate”,Lang.bind(this,this._onActivate));
this.application.connect(“startup”,Lang.bind(this,this._onStartup));
},
_onActivate:function(){
这是一个窗口。全部显示();
},
_启动时:函数(){
this.model=new Gtk.ListStore();
this.model.set_column_types([GObject.TYPE_STRING]);
让renderer=new Gtk.cellrenderText();
让dir=Gio.file_new_for_path(GLib.get_home_dir());
目录枚举子项异步(“标准::*”,
Gio.FileQueryInfoFlags.NONE,
GLib.PRIORITY_默认,
无效的
Lang.bind(this,this.\u枚举ChildrenAsyncCallback),
无效);
/*
*我希望在读取所有文件后运行这一行。
*
*/
this.model.set_sort_column_id(0,Gtk.SortType.升序);
let column=new Gtk.TreeViewColumn({
标题:“文件”
});
column.pack_start(渲染器,true);
添加_属性(渲染器,“文本”,0);
let view=new Gtk.TreeView({
模特儿:这个
});
视图。追加_列(列);
let scrolled=new Gtk.ScrolledWindow();
scrolled.hscrollbar_policy=Gtk.PolicyType.AUTOMATIC;
scrolled.Vscrollbar_policy=Gtk.PolicyType.AUTOMATIC;
滚动。添加(视图);
此.u窗口=新的Gtk.ApplicationWindow({
应用程序:这个应用程序,
默认高度:300,
默认宽度:400,
标题:“家,甜蜜的家”
});
此._窗口添加(滚动);
}
});
让家=新家();

home.application.run(ARGV)如果我正确理解了您要做的事情,那么您需要类似的东西。不幸的是,GJS还没有promise库

我建议在您的enumerate children回调中执行类似的操作(我已经编辑了一些与我试图说明的内容无关的部分):


乍一看,这似乎在清除第一个元素和添加第二个元素之间存在竞争条件,但是在主循环的下一次迭代之前,
load\u contents\u async
回调不会开始被调用,因此您在那里应该是安全的。

谢谢您,ptomato!我没有想到这种方法。根据Gio课程的不同,阅读起来要容易得多。然而,在我接受你的回答之前,我需要请你考虑一个建议。运行代码后,我得到一个
类型错误:this.model未定义。将
函数(f,r){}
替换为
Lang.bind(这个函数(f,r){})
避免了错误消息并使排序工作正常。GNOME的wiki页面上说,
Lang.bind
这个
在闭包中按预期工作所必需的。你是对的,尽管建议有点过时了-
Lang.bind()
不再是必需的,因为GJS已经支持
Function.bind()
很多年了,事实上,对于fat arrow函数,它自动绑定
,以及GJS 1.40。我已经更新了这个示例,使用了一个胖箭头函数。
_enumerateChildrenAsyncCallback: function(dir, result) {
  let fileEnumerator = dir.enumerate_children_finish(result);
  let displayName, file, fileInfo, fileType, iter;

  let pendingOperations = new Set();

  while ((fileInfo = fileEnumerator.next_file(null))) {
    file = dir.get_child(fileInfo.get_name());
    fileType = file.query_file_type(Gio.FileQueryInfoFlags.NONE, null);
    if (fileType != Gio.FileType.REGULAR) continue;

    pendingOperations.add(file);

    file.load_contents_async(null, (file, result) => {
      let [success, contents, etag] = file.load_contents_finish(result);

      pendingOperations.delete(file);
      if (pendingOperations.size === 0)
        this.model.set_sort_column_id(0, Gtk.SortType.ASCENDING);
    });
  }
},