难以包装javascript行为并将其保留以供日后使用

时间:2014-07-08 18:30:03

标签: javascript promise q

我正在使用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();
      });
   }
}

问题是我不想让它在我排队的瞬间运行。我基本上想要构建列表,然后再运行它。我使用reduce

中的Q.js函数运行列表
{
   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;
}

_layout

<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>
}

2 个答案:

答案 0 :(得分:6)

你可以使用一个闭包。

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();
    };
});

答案 1 :(得分:1)

我认为你应该做点什么

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()返回其他承诺的函数。