【问题标题】:Difficulty wrapping a javascript behavior and holding it for later难以包装 javascript 行为并将其保留以备后用
【发布时间】:2014-07-09 03:19:32
【问题描述】:

我正在使用 javascript 进行编程并使用Promises,现在使用Q.js。我终于明白了自己在做什么,但在特定行为上遇到了困难。

我有一种情况,我重复了几次相当相似的代码。它基本上是这样的......

{
   // start
   var deferred = Q.defer();

   // do something {
      deferred.resolve();
   }

   return deferred.promise;
}

好的,这一切都很好,但是每次都重复这一切很烦人,所以我试图把它包起来。这只是一个示例,它不是整个 javascript 文件,因为大部分其他部分都不相关。

{
   var list = [];
   queue = function(f) {
      var deferred = Q.defer();
      list.push(f(deferred));
      return deferred.promise;
   }

   {
      queue(function(deferred){
         // do some work
         // we want the deferred here so we can resolve it at the correct time
         deferred.resolve();
      });
   }
}

问题是我不希望它在我排队的那一刻运行。我基本上想建立列表,然后再运行它。我正在使用Q.js 中的reduce 函数运行列表

{
   return list.reduce(function(i, f) {
      return i.then(f);
   }, Q());
}

但这有点与我的目标背道而驰,因为我真的不打算在它们排队的同时运行它们。有没有办法保存执行以供以后使用,并且仍然通过函数传递延迟对象?

更新

有人问我希望代码做什么,这是一个公平的问题。我会尽力解释。这样做的目的是拆分逻辑,因为我使用的是ASP.NET MVC,所以我有_Layout 页面,然后是普通视图 - 所以在其他事情完成之前,有些逻辑无法运行,但有时是以每页为基础。这种方法是为了解决这个问题而设计的。

基本上它是这样工作的......

Loader.js

由于缺乏更好的术语或当前的实现,这是一个全局对象。我计划最终改变这一点,但一步一步来。

{
   var Loader = {};
   var list = [];

   initialize = function() {
      Q().then(step1).then(step2).then(process).then(finalStep);
   };

   queue = function(f) {
      // push the given function to the list
   };

   process = function() {
      return list.reduce(function(i,f){ 
         return i.then(f);
      }, Q());
   };

   step1 = function() { // generic example
      // create a promise
      return deferred.promise;
   }; // other steps are similar to this.

   return Loader;
}

_布局

<head>
   @RenderSection("scripts", false)
   <script type="text/javascript">
      // we have the loader object already
      Loader.initialize();
   </script>
</head>

索引

@section Scripts {
   <script type="text/javascript">
      Loader.promise(function(deferred){
         // do something here.
         deferred.resolve();
      }));
   </script>
}

【问题讨论】:

  • 我不明白你的问题是什么。传递给run promises in a list,或者传递给promisify a functionality,传递一个deferred(如“输出参数”)?
  • 如果不能尽快开始执行,您想如何开始?
  • 这些问题真的很好,我更新了问题以更好地说明手段和意图。如果我需要添加更多详细信息,请告诉我。
  • 那张大图中哪里有新任务queue()d?在一些初始化step1/step2s 之后,您似乎想process 他们,但list 实际上仍然是空的?
  • 在流程的这一点上,列表由排在第一位的简单优点填充。在 DOM 准备好之前不会进行初始化。最终,我会将其与实际事件联系起来以进行正确的流控制,但正如现在所写的那样,将事物放入队列更像是一场竞赛。

标签: javascript promise q


【解决方案1】:

你可以使用闭包。

queue(function(deferred) {
    return function() {
        // this is the actual function that will be run,
        // but it will have access to the deferred variable
        deferred.resolve();
    };
});

【讨论】:

  • 哦,哇,我不敢相信我没有想到这一点。我很快就会试一试。
  • 这正是我想要做的!非常棒!非常感谢。
【解决方案2】:

我认为你应该这样做

var Loader = {
    promise: function(construct) {
        var deferred = Q.defer();
        construct(deferred);
        return deferred.promise;
    },
    queue: function(f) {
        this.ready = this.ready.then(f);
    },
    ready: Q.Promise(function(resolve) {
        window.onload = resolve; // or whatever you need to do here
        // or assign the resolve function to Loader.initialize and call it later
    })
};

然后是 Loader.queue() 返回其他承诺的函数。

【讨论】:

  • 哇,这也很酷。这确实成功地做了同样的事情。目前,我不会切换到这个模型,但我会更多地研究它,看看我能做什么。我坚信总能找到两种方法来做任何你不理解的事情,而不是仅仅采取你找到的第一个解决方案。非常感谢!
猜你喜欢
  • 1970-01-01
  • 2014-07-01
  • 2014-05-25
  • 2020-01-25
  • 2019-02-22
  • 1970-01-01
  • 1970-01-01
  • 2011-11-14
  • 1970-01-01
相关资源
最近更新 更多