Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difficulty wrapping a javascript behavior and holding it for later

I am getting into programming with javascript and using Promises, right now using Q.js. I have finally gotten to a point where I understand what I am doing, but am having a difficult time with a specific behavior.

I have one situation where I have reasonably similar code repeated several times. It basically goes like this ...

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

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

   return deferred.promise;
}

Okay, that's all fine and good, but repeating all of this every time was getting annoying, so I attempted to wrap it up in something. This is just an example, it is not the entire javascript file, since most of the other parts are not relevant.

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

The problem is that I don't want this to run the instant I queue it up. I basically want to build the list, and then run it later. I am running the list using the reduce function in Q.js

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

But this is kind of counter to my goal, since I really don't intend to run them at the same time they are queued. Is there a way to save the execution for later and still pass the deferred object through the function?

Update

I was asked what I expect the code to do, which is a fair question. I'll try to explain. The purpose of this is to split up the logic because I am using ASP.NET MVC, and so I have _Layout pages, and then normal views - so there is logic that cannot run until other things are completed, but some times that is on a per-page basis. This method was contrived to deal with that.

Essentially it works like this ...

Loader.js

This is, for lack of a better term or current implementation, a global object. I have plans to change that eventually, but one step at a time.

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

Index

@section Scripts {
   <script type="text/javascript">
      Loader.promise(function(deferred){
         // do something here.
         deferred.resolve();
      }));
   </script>
}
like image 960
Ciel Avatar asked Jul 08 '14 18:07

Ciel


People also ask

What are the problems with JavaScript?

These days, most cross-browser JavaScript problems are seen: When poor-quality browser-sniffing code, feature-detection code, and vendor prefix usage block browsers from running code they could otherwise use just fine. When developers make use of new/nascent JavaScript features, modern Web APIs, etc.)

When there is a problem with JavaScript code there are generally two types of errors?

Namely, with JavaScript, most of our errors fit into two categories: syntax errors and runtime errors. A syntax error is a problem with the grammar in our code. Syntax errors mostly come in the form of misspelled keywords, missing or open brackets, or missing parentheses or punctuation.


2 Answers

You could use a closure.

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();
    };
});
like image 66
dpk2442 Avatar answered Sep 30 '22 17:09

dpk2442


I think you should do something like

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

Then Loader.queue() functions that return other promises.

like image 44
Bergi Avatar answered Sep 30 '22 15:09

Bergi