Further simplify an 'API' that's async - javascript

So let's say I have this code:
function DBManager()
{
this.getContactsList = function(cb)
{
$.post('/post/getContactsList', function (contacts) {
cb(contacts);
});
}
}
Then this:
var DBManager = new DBManager();
DBManager.getContactsList(function (contacts) {
console.log(contacts);
});
I actually have a lot more functions inside DBManager, and the above code with the callbacks seems redundant so I was wondering if there would be more optimal ways to make calls to DBManager?

You could use promises in JavaScript to accomplish the same functionality provided by callbacks. If you are using RSVP.js or something similar.

function DBManager()
{
this.getContactsList = function()
{
return $.post('/post/getContactsList');
}
}
var DBManager = new DBManager();
DBManager.getContactsList().then(function (contacts) {
console.log(contacts);
});

Related

self-executing anonymous functions and call it again

I want to do something like this:
var build= (function(){
//my function body
})();
function test(){
//somthing then call build
build() //i want to call build function again in my code
}
How can I do this?
I tried this in angular:
var buildRoot = (() => {
$SubNode.get({
TypeID: vendorAdminService.NodeType.Category
}, function(data: vendorAdminService.IGetNodeParameters) {
$scope.ProductTree = data.TreeNodeModelItem;
$scope.AjaxLoading = false;
}, function(err) {
// alert(err)
})
})();
$mdDialog.show(confirm).then(function() {
$Category.Remove(node.ID)
buildRoot
}, function() {
});
but it does not work.
Anybody can guide me??
You need to return a function in your IIFE.
If you IIF is not trivial and has many functionalities you could also consider using Reveal Module Pattern.
var build = (function() {
var f = function() {
console.log('hello');
};
f();
return f;
})();
function test() {
build();
}
test();
Just use a named function.
Your IIFE needs to return a function, for later calling. But then is no need for an anonymous function.
function build() {
//my function body
}
or
var build = function () {
//my function body
};
var build = (function() {
var init = function() {
// magic code
};
return {
init: init
}
}());
function test() {
build.init()
}
test();
You include all your functionalities inside your build object, and you'll be able to call them as soon as you return them from inside that object. This effectively is called the revealing module pattern
For more information, read this
I see that there are missing semi-colons ";"
$mdDialog.show(confirm).then(function() {
$Category.Remove(node.ID);
buildRoot();
}, function() {
});

How can I make a waterfall Q promises?

let's take this as an example:
I have 3 urls in an array urls
require function returns a promise which just makes an $http call
this is a working code, but as the array can be '1 to n' this is obviously not what I want.
I need the 3 require as a waterfall, not in parallel.
in the last promise, I need to resolve a final promise which is the var deferred.
require(urls[0]).then(function () {
require(urls[1]).then(function () {
require(urls[2]).then(function () {
deferred.resolve();
});
});
})
this approach is not working, because this will do all the $http calls in parallel.
var promises = [];
angular.forEach(urls, function (value) {
promises.push(require(value));
});
$q.all(promises).then(function () {
deferred.resolve();
});
is there a nice way to do this with a for/cycle?
Create a function to handle the iterations:
function go (urls) {
if (urls[0]) {
require(urls[0]).then(function () {
go(urls.slice(1));
});
}
}
go(urls);
Here is an excellent blog post: http://www.codeducky.org/q-serial/
I will share only the part that is relevant.
First we define this helper method:
function serial(tasks) {
var prevPromise;
angular.forEach(tasks, function (task) {
//First task
if (!prevPromise) {
prevPromise = task();
} else {
prevPromise = prevPromise.then(task);
}
});
return prevPromise;
}
Then we use it.
serial([
function() { return require(urls[0]) },
function() { return require(urls[1]) },
function() { return require(urls[2]) }
]).then(function () {
deferred.resolve();
});
Just to offer another way, there's a "one-line" solution to this without having to make another method:
return promises.reduce($q.when, promises[0]);
See demo here: http://plnkr.co/edit/xlGxYj57lzXdAMM5Iv6s?p=preview (I changed the default $q.when to something else to show handling each promise.)
Update: Made the plunker more representative of OP's scenario.

Promise loops (bluebird) - wrap object in async

I have a question about promises.
I am using Bluebird Promise library and build a small async library with it.
I am trying to waterfall promises with the use of a function.
Say I use promises like so:
Promise.resolve()
.then(function () {
console.log("called 1")
return 1;
}).then(function () {
return new Promise (function (res, rej) {
setTimeout(function () {
console.log("called 2")
res(2);
}, 1500);
});
}).then(function () {
console.log("called 3")
return 3;
});
This does in fact wait in a loop and return 1,2,3 in order.
How do I wrap it into a function so that I can do something like this:
a();b();c();, or a().b().c(); where a() puts something onto a chain, b() puts something onto a chain, and c() puts something onto a chain in order.
Since then() returns a new promise, it can all go out of order, so something like
does not work:
var promise = Promise.resolve();
function a () {
promise.then(function () {
// do sync/async
});
}
function b () {
promise.then(function () {
//do sync/async
});
}
function c ...
Thank you for your time :]
I'm not sure what the goal is here. Do you want to have an arbitrary number of things run in sequence where the sequence is known in advance? Or is this a case where the sequence is discovered as you go? The NodeJS streams interface is a lot better for processing an unknown number of things sequentially (#tadman)
Sequence is discoverable, goal is to have ability to call a().b().c() or b().a().d(). Async library on a client-side.
Update: If I do as #zerkms says it does not work as expected. My bad, should work ok, but with lack of context/code did not give me enough info to expand on. Still thank you for your answer, as it gave me more food for thought.
Update: See my answer
You could use a scoped prototype and just add those methods there
Promise.prototype.a = function() {
return this.then(function() {
console.log("called 1")
return 1;
});
};
Promise.prototype.b = function() {
return this.delay(1500).then(function() {
console.log("called 2")
return 1;
});
};
Promise.prototype.c = function() {
return this.then(function() {
console.log("called 3")
return 3;
});
};
I use this to create neat DSLs e.g. with git:
https://gist.github.com/petkaantonov/6a73bd1a35d471ddc586
Thanks to #tadman I came up with this so far, seems to work as I expect it to.
The problem was that I did not update the promise before calling then on it, and it was branching instead of calling it in sequence.
And this is what I wanted - to turn an object that has both sync/async into async to allow chaining. Petka (#Esailija) also shows great example of building DSLs above (semvar version bumping & git pushing) by extending bluebird library, but for my purposes this is enough.
var Sample = function () {
this.promise = Promise.resolve();
};
Sample.prototype.a = function () {
this.then(function () {
console.log("1");
});
return this;
};
Sample.prototype.b = function () {
this.then(function () {
return new Promise(function (res, rej) {
setTimeout(function() {
console.log("2");
res();
}, 500);
});
});
return this;
};
Sample.prototype.c = function () {
this.then(function () {
console.log("3");
})
return this;
};
Sample.prototype.chainPromise = function (func) {
this.promise = this.promise.then(func);
};
var s = new Sample();
s.a().b().c();
or even then instead of chainPromise?
Sample.prototype.then = function (func) {
this.promise = this.promise.then(func);
return this.promise;
};

Correct way to continue on after a generator function

I have the following generator function:
BulkLoader.prototype.load = function(password) {
var self = this;
return async(function * () {
try {
self.users = yield getJSON('/users');
self.contacts = yield getJSON('/contacts');
self.companies = yield getJSON('/companies');
return self;
} catch (err) {
throw err;
}
});
};
The asyc method looks like this, which I took from the Q library:
export default function async(generatorFunc) {
function continuer(verb, arg) {
var result;
try {
result = generator[verb](arg);
} catch (err) {
return RSVP.Promise.reject(err);
}
if (result.done) {
return result.value;
} else {
return RSVP.Promise.resolve(result.value).then(callback, errback);
}
}
var generator = generatorFunc();
var callback = continuer.bind(continuer, "next");
var errback = continuer.bind(continuer, "throw");
return callback();
}
My calling code looks like this:
var bulkLoader = new GeneratorBulkLoader();
bulkLoader.load()
.then(render)
.catch(errorHandler);
This seems a bit weird having to work with promises after calling a generator function.
How do other people handle their calling code when working with generators?
This seems a bit weird having to work with promises after calling a generator function.
Why? The API is still a promise. Whether it did use generators internally does not make a difference.
How do other people handle their calling code when working with generators?
You can always use generators to sugar your calling code as well:
async(function* () {
var bulkLoader = new GeneratorBulkLoader();
try {
yield render(yield bulkLoader.load())
} catch(e) {
errorHandler(e);
}
});

Java script modify function at run time

enter code hereI have the following code
function a(){alert("a");}
I want to create a function b as
function b(){alert("a"); alert("b");}
My approach is something like
var b = a + alert("b");
This is of course not working. But I am wondering if there is some kind of library supporting this.
Edit: Maybe I need to describe my scenario so that its more clear what I want to achieve.
I am using async.js library to handler multiple async calls. My code looks like
var values = {};
...
function all() {
var allDfd = $.Deferred();
async.parallel(
[function (callback) {
remoteCall(function (result) {
values.v1 = result;
callback(null, 'one');
});
},
function (callback) {
remoteCall(function (result) {
values.v2 = result;
callback(null, "two");
});
},
function (callback) {
remoteCall(function (result) {
values.v3 = result;
callback(null, "three");
});
}], function (err, results) {
allDfd.resolve();
});
return allDfd.promise();
}
Clearly there are a lot of repetitive code that bothers me. So my idea is to create a function asyncCall to perform the boilerplate tasks. The idea is
var values = {};
...
function all() {
var allDfd = $.Deferred();
function getAsyncCall (func, innerCallback, callback) {
return function asyncCall(func, innnerCallback, callback){
func(innerCallback + callback(null)); // combine innerCallBack and callback code
}
}
async.parallel(
[getAsyncCall(remoteCall, function(result){values.v1=result;},callback),
getAsyncCall(remoteCall, function(result){values.v2=result;},callback),
getAsyncCall(remoteCall, function(result){values.v3=result;},callback),
], function (err, results) {
allDfd.resolve();
});
return allDfd.promise();
}
The line with the comment is what I am pondering. I am trying to create a new function that combines inner and outer callbacks.
You can do
var b = function() { a(); alert('b'); }
You could write:
var a=function(){alert("a");}
var b=function(){a(); alert("b");}
And to go a little further, you can even write a whole function composition function:
function compose( functions ) {
return function(){
for(var i=0; i!=functions.length; ++i) {
functions[i]();
}
};
}
var c=compose( [a, function(){ alert("b"); }] );
(See it at work at http://jsfiddle.net/xtofl/Pdrge/)

Categories