Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/364.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 重新进入安全异步函数执行_Javascript_Coffeescript_Windows Runtime_Promise_Winrt Async - Fatal编程技术网

Javascript 重新进入安全异步函数执行

Javascript 重新进入安全异步函数执行,javascript,coffeescript,windows-runtime,promise,winrt-async,Javascript,Coffeescript,Windows Runtime,Promise,Winrt Async,我有一个saveAsync方法,可以从应用程序的其他几个部分调用。其中一些代码路径不是来自主UI线程,而是来自其他异步操作,如从套接字/文件读取数据 在我的saveAsync函数中,我调用WinRT的StorageFile流写入函数。一次只允许一个文件的写入程序。因此,我必须将对我的saveAsync函数的多个连续调用排队,并按顺序执行它们。这是我现在正在使用的代码: SaveableMixin = { savesPending: 0, saveAsync: function() {

我有一个
saveAsync
方法,可以从应用程序的其他几个部分调用。其中一些代码路径不是来自主UI线程,而是来自其他异步操作,如从套接字/文件读取数据

在我的
saveAsync
函数中,我调用
WinRT
StorageFile
流写入函数。一次只允许一个文件的写入程序。因此,我必须将对我的
saveAsync
函数的多个连续调用排队,并按顺序执行它们。这是我现在正在使用的代码:

SaveableMixin = {
  savesPending: 0,
  saveAsync: function() {
    self = this
    logger.debug("Save requested (_cachedFile=" + self._cachedFile + ")");
    if (self.saving) {
      self.savesPending += 1;
      logger.debug("saveAsync: already saving, " + self.savesPending + " pending now");
      return self.saving;
    }
    return self.saving = getFileNameAsync(self.serialNumber).then(function(file) {
      logger.debug("saveAsync: saving...");
      return self.node.ownerDocument.saveToFileAsync(file);
    }).then(null, (function(error) {
      return logger.error("saveAsync: failed but " + self.savesPending + " saves pending - good luck!", error);
    }).then((function() {
      logger.debug("saveAsync: saved and " + self.savesPending + " pending");
      self.saving = null;
      if (self.savesPending) {
        self.savesPending = 0;
        return self.saveAsync();
      }
    });
  }
}
CoffeeScript原始代码:

savesPending: 0
saveAsync: () ->
  logger.debug("Save requested (_cachedFile=#{@_cachedFile})")
  if @saving
    @savesPending += 1
    logger.debug("saveAsync: already saving, #{@savesPending} pending now")
    return @saving
  @saving = getCachedFile(@serialNumber)
  .then (file) =>
    logger.debug("saveAsync: saving...")
    @node.ownerDocument.saveToFileAsync(file)
  .then null, (error) =>
    logger.error("saveAsync: failed with inspection #{@serialNumber} but #{@savesPending} saves pending - good luck!", error)
  .then =>
    logger.debug("saveAsync: saved and #{@savesPending} pending")
    @saving = null
    if @savesPending
      @savesPending = 0
      return @saveAsync()
如您所见,我记得上次保存时承诺知道操作正在运行。然而,我仍然会得到一个
访问被拒绝
异常,原因是某些代码路径设法将
保存
视为空,因此认为现在保存操作正在进行。当变量即将分配给第一个调用者时,当第二个异步操作(例如套接字读取)完成并调用
saveAsync
,而第一个调用者获得分配的
saving
变量时,似乎会发生这种情况

<>在C++中,我会使用锁来防止。在JavaScript世界中可以做什么

更新 这将在调试器中生成以下输出:

2014-12-07 23:46:52,286 - [inspection - DEBUG] - saveAsync: get file for save 0
2014-12-07 23:46:52,289 - [inspection - DEBUG] - saveAsync: get file for save 0
2014-12-07 23:46:52,349 - [inspection - DEBUG] - saveAsync: got file for save 0 ...
2014-12-07 23:46:52,444 - [inspection - DEBUG] - saveAsync: got file for save 0 ...
2014-12-07 23:46:52,446 - [inspection - DEBUG] - saveAsync: get file for save 1
2014-12-07 23:46:52,447 - [inspection - DEBUG] - saveAsync: got file for save 1 ...

当然,这是对有问题的文件的双重访问,并与AV一起崩溃。

在JavaScript世界中,您可以使用承诺来实现这一点,承诺抽象了一系列异步操作,您可以将其用作队列

SaveableMixin = {
  queue: WinJS.promise.as(), // empty start of queue
  saveAsync: function() {
    this.queue = this.queue.then(function(){ // update the queue
      return getFileNameAsync(self.serialNumber).then(function(file) {
          logger.debug("saveAsync: saving...");
          return self.node.ownerDocument.saveToFileAsync(file);
    })..then(null, (function(error) {
      return logger.error("saveAsync: failed good luck!", error);
    }).then((function() {
      logger.debug("saveAsync: saved and " + self.savesPending + " pending");
    });
  }
}

不确定这是否是问题的原因,但您没有正确关闭括号。把这段代码放到jslinter或soemthing中,你会看到一些括号被打开了。谢谢,这段代码是我从coffeescript源代码中手工编辑的,我删除了一些杂乱的内容。是的,一些括号可能没有正确闭合。
self
缺少一个
var
源于咖啡清理?你可能还想发布原始的咖啡脚本。我不确定排队是如何工作的<代码>保存开销在每次发出请求时都会递增,而保存仍在进行,但附带的数据(
.serialNumber
?)存储在哪里?为什么
savespensing
会重置为0,而不是递减?请详细说明:-)@Bergi。serialNumber是您将该类与之混合的类的成员。我增量
saveexpensing
只知道在保存文件时,有更多的请求保存它。由于所有这些请求最终都会保存XML的最新状态,因此我只需要知道是否有挂起的保存,并再次保存文件。我本可以使用boolan而不是递增计数器,但这样我就可以看到在保存过程中我接到了多少个呼叫。这可能与我当前遇到的竞争条件相同。在分配this.queue的“n”时刻,另一个完成处理程序可能会调用saveAsync并将this.queue分配给其他对象。否?@philk Fun fact-大多数上下文中,尤其是WinJS应用程序中的JavaScript都是单线程的。在这些上下文中,它是基于事件和单线程的。没有两个作业可以同时进行。我也这么认为。但是我的代码已经可以用了,不是吗?我可以看到进入saveAsync方法的方法的堆栈跟踪,它们都来自主线程,是的。然而,它可能试图同时从两个不同的代码路径写入文件。有一点需要澄清:JavaScript中的UI线程是单线程的,但WinRT异步操作确实会委托给其他线程。其他线程对已完成/错误/进度处理程序的回调将进入UI线程,因此您一次只能处理一个操作的结果,但多个操作可能同时发生,因此会发生冲突。@KraigBrockschmidt MSFT JavaScript是单线程的,不是吗?我的意思是,就像在Node中一样,在其他线程中运行的其他东西不是userland代码。
SaveableMixin = {
  queue: WinJS.promise.as(), // empty start of queue
  saveAsync: function() {
    this.queue = this.queue.then(function(){ // update the queue
      return getFileNameAsync(self.serialNumber).then(function(file) {
          logger.debug("saveAsync: saving...");
          return self.node.ownerDocument.saveToFileAsync(file);
    })..then(null, (function(error) {
      return logger.error("saveAsync: failed good luck!", error);
    }).then((function() {
      logger.debug("saveAsync: saved and " + self.savesPending + " pending");
    });
  }
}