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?
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 ...
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;
}
<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>
}
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.)
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.
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();
};
});
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With