试图理解 JS 有望消除竞争条件

Trying to understand JS promises to eliminate a race condition

我正在使用纯 JS 开发一个项目,我遇到了一个我试图消除的竞争条件。我刚刚遇到了承诺的概念,但我正在为它们的工作方式而苦苦挣扎。

这是我正在尝试做的事情:用户可以将文件拖到拖放区,然后在图库中创建该文件的表示,并且它应该经历一个由进度表示的过程酒吧:

var tracker = {}; // this will have dropped-file objects added
var gallery = document.getElementById('gallery');

function newFile(id) {
     (declaration of various properties)
     var container = document.createElement('DIV');

     (then the creation of various elements within the container)

     var progress = new progbar(id);  // goes to a constructor to create the progress bar
     container.appendChild(progress);
     gallery.appendChild(container);

     this.id = id;
     this.container = container;
     this.progress = progress;

     this.removeMe = function() {
          this.progress.endprog();
          delete tracker[this.id];
     }

     return this;
}

然后在程序的其他地方,当用户将文件拖放到拖放区时,我们添加一个tracker[id] = new newFile(id);.

如果用户点击进度条的"cancel"问题就来了link:调用了文件对象的removeMe()方法,它调用了进度条的末尾this.progress.endprog(),然后从跟踪器对象中删除自身。

如果用户删除了同一个文件,那么我会检查 tracker,如果该文件存在,该过程将结束并向用户发出警报。但如果他们已经开始处理该文件并取消了它,我希望他们能够再次删除该文件。因此,虽然我确实留下了已取消文件的 div(如此标记),但文件的对象已从 tracker 中消失,因此可以再次删除它。

我关心的是:

this.progress.endprog();
delete tracker[this.id];

这两件事都需要发生,但是如果 progress.endprog{} 在文件(以及进度对象本身)被删除之前还没有完成,那么我担心会把事情搞砸。

我最初对删除有一个 set Timeout,但仍然感觉像是一个竞争条件,我正在寻找更优雅的东西并消除竞争条件。但我正在挣扎。承诺有帮助吗?我还缺少其他方法吗?

编辑:添加更多细节

这里有一条信息很重要,我忘了包括:进度条对象进行各种自引用:

function progbar(id) {
     (declaration of various properties)
     var bar = document.createElement('DIV');
     [file container].appendChild(bar);
     this.bar = bar;
     this.width = 0;
     this.fillup;

     this.startprog = function () {
          this.fillup = setInterval( [process to check for correct length] );
     }

     this.endprog = function () {
          [other stuff, and then...]
          clearInterval(this.fillup);
          [then more stuff]
     }

     return this;
 }

所以你可以看到至少有一个对 setInterval 的引用,它存储为对象的 属性。如果文件对象在 endprog() 到达此引用之前被删除,它不会尝试访问不再存在的 属性 吗?

试试这个:

 this.id = id;
 this.container = container;
 this.progress = progress;

 this.removeMe = function(id) {
      this.progress.endprog();
      delete tracker[id];
 }

回答你的评论,也许一个选项可以是将 delete tracker[this.id]; 移动到 endprog 函数内,这样你就可以确保在这个函数的末尾调用,其他更复杂的选项可以使用一个只删除具有给定标志的跟踪器的进程。