how to sync between two functions - javascript

I have two functions that I want to call to third function when the other functions( one and two ) will be finished.
I need that the first function and the second function will be called Asynchronous.
for example
var func1 = function( do something..... return arr )
var func2 = function ( do something ..... return arr2 )
if ( arr.length > 0 && arr2.length > 0 )
var func3 = function( do something )
my qeustions:
what is the best way to do it ?
How I call to function in Asynchronous way ?

If you have jQuery, you could use their Deferred objects:
var func1 = function () {
var dfd = $.Deferred();
setTimeout(function () {
// do your processing
dfd.resolve(arr1);
}, 0);
return dfd.promise();
};
var func2 = function () {
var dfd = $.Deferred();
setTimeout(function () {
// do your processing
dfd.resolve(arr2);
}, 0);
return dfd.promise();
};
$.when(func1(), func2()).then(function (arr1, arr2) {
if ( arr.length > 0 && arr2.length > 0 ) {
func3();
}
});
Related questions:
How can jQuery deferred be used?
How can I create an Asynchronous function in Javascript?

Pass the func3 function as a callback and check inside your callback if both arrays are filled.
var func1 = function(callback) ( do something; callback();..... return arr );
var func2 = function(callback) ( do something; callback(); ..... return arr2 );
var func3 = function() {
if(arr != undefined && arr2 != undefined){
//do stuff
}
};
func1(func3);
func2(func3);

var arr1 = [], arr2 = [];
function arraysAreReady() {
if(arr1.length && arr2.length) {
func3();
}
}
var func1 = function() {
var localArray = [];
/// create the local array
arr1 = localArray;
arraysAreReady();
}
var func2 = function() {
var localArray = [];
/// create the local array
arr2 = localArray;
arraysAreReady();
}
func1(); funct2();
when func1 has created the first array it wil assign it to the global variable arr1 and call arraysAreReady() function. when func2 has created the second array it will asign it to the global variable arr2 and call arraysAreReady().
the arraysAreReady() function checks on each call if the 2 global arrays are not empty. Is they are not the it will call the third function (func3)

If your program logic is suitable, you can imitate asynchronous behavior in javascript by doing partial processing and using setTimeout() function as follows:
var result1 = []
var result1Ready = false;
var result2 = []
var result2Ready = false;
func1 = function(list, start, end) {
if(start>=end) {
result1Ready = true;
}
else {
partialEnd = start+10>end ? end : start+10;
for(i=start;i<partialEnd;i++) {
//process 10 items
//append results to array result1
}
//schedule second partial process
setTimeout(function () { func1(list, partialEnd, end); }, 50);
}
};
func2 = function(list, start, end) {
//similar to func1...
};
waitResults = function() {
if(result1Ready && result2Ready) {
func3();
}
else {
setTimeout(function () { waitResults(); }, 50);
}
};
setTimeout(function () { func1(someList, 0, listLength); }, 5);
setTimeout(function () { func2(someOtherList, 0, otherListLength); }, 5);
setTimeout(function () { waitResults(); }, 10);

Related

Rxjs observing object updates and changes

I am currently trying to observe any changes to a given object including all of it's elements.
The following code only fires when an object[x] is updates, but not if individually updating object[x]'s elements such as object[x][y]
<script>
var elem = document.getElementById("test1");
var log = function(x) {
elem.innerHTML += x + "<br/><br/><br/>";
};
var a = [{a:1,b:2},
{a:2,b:5}
];
var source = Rx.Observable
.ofObjectChanges(a)
.map(function(x) {
return JSON.stringify(x);
});
var subscription = source.subscribe(
function (x) {log(x);},
function (err) {log(err);},
function () {log('Completed');}
);
a[0] = a[1];
</script>
This code runs and fires correctly.
however. if I instead to this
a[0]['a'] = 3;
Then nothing happens.
EDIT
A better way to phrase this, how can I observe changes from an array of objects?
If you want only the nested object changes:
var source = rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
});
If you also want changes like a[0] = a[1]:
var source = rx.Observable.merge(
rx.Observable.ofArrayChanges(a),
rx.Observable.from(a).flatMap(function(item) {
return rx.Observable.ofObjectChanges(item);
})
);
The flatMap or selectMany (they are the same function) will allow you to iterate over a value and execute a function that returns an Observable. The values from all these Observables are "flattened" onto a new stream that is returned.
http://reactivex.io/documentation/operators/flatmap.html
Perhaps something like this by merging two Observables (one for the array and the other observing the elements of the array):
var a = [
{a:1,b:2},
{a:2,b:5}
];
var source1 = Rx.Observable.ofArrayChanges(a).map(function(x) {
return JSON.stringify(x);
});
var source2 = Rx.Observable
.fromArray(a.map(function(o, i) { return [o, i]; }))
.flatMap(function(oi) {
return Rx.Observable.ofObjectChanges(oi[0])
.map(function(x) {
var y = {
type: x.type,
object: x.object,
name: x.name,
oldValue: x.oldValue,
arrayIndex: oi[1] // pass the index of the member that changed
};
return JSON.stringify(y);
});
})
source = source1.merge(source2)
var subscription = source.subscribe(
function (x) {log(x);},
function (err) {log(err);},
function () {log('Completed');}
);
a[0] = a[1]
a[1]['b'] = 7
Thanks to #electrichead here we're not using concatMap because the sources that we made by ofObjectChanges and ofArrayChanges never complete.
Here's a working example of Rx.Observable.ofNestedObjectChanges simple implementation, you can get the gist of it and implement you own.
http://jsbin.com/wekote/edit?js,console
Rx.Observable.ofNestedObjectChanges = function(obj) {
if (obj == null) { throw new TypeError('object must not be null or undefined.'); }
if (typeof Object.observe !== 'function' && typeof Object.unobserve !== 'function') { throw new TypeError('Object.observe is not supported on your platform') }
return new Rx.AnonymousObservable(function(observer) {
function observerFn(changes) {
for(var i = 0, len = changes.length; i < len; i++) {
observer.onNext(changes[i]);
}
}
Object.observe(obj, observerFn);
//Recursive observers hooks - same observerFn
traverseObjectTree(obj, observerFn);
function traverseObjectTree(element, observerFn){
for(var i=0;i<Object.keys(element).length;i++){
var myObj = element[Object.keys(element)[i]];
if(typeof myObj === "object"){
Object.observe(myObj, observerFn);
traverseObjectTree(myObj,observerFn);
}
}
}
return function () {
Object.unobserve(obj, observerFn);
};
});
};
//Test
var json = {
element : {
name : "Yocto",
job : {
title: "Designer"
}
},
element1: {
name : "Mokto"
}
};
setTimeout(function(){
json.element.job.title = "A Great Designer";
},3000);
var source = Rx.Observable.ofNestedObjectChanges(json);
var subscription = source.subscribe(
function (x) {
console.log(x);
},
function (err) {
console.log('Error: %s', err);
},
function () {
console.log('Completed');
});
json.element.name = "Candy Joe";

influence Javascript function invokation

I want to invoke function X everytime any other function is invoked. I want to keep this as generic as possible.
having these two functions
function x(){ console.log("invoke BEFORE"); }
function someFunction(something){ console.log(something); }
When someFunction is invoked
someFunction("testoutput");
I want the console to output this:
>> invoke BEFORE
>> testoutput
I also want this behaviour to apply to any function of a certain object.
For example:
var myFunctions = {
first:function(){/* do something */},
second:function(){/* do something else*/}
}
myFunctions.before(function(){/do something before/});
Anyone know a solution?
EDIT:
I have come up with a solution like this:
Object.prototype.before = function(x){
for(var key in this){
if(typeof this[key] === "function")
this[key] = (function(x, f) {
var g = f;
return (function() {
x();
return g.apply(this, arguments);
});
}(x, this[key]));
}
}
var test = { func: function(){console.log("test")}};
test.before(function(){console.log("before")});
test();
results in:
>> before
>> test
YAAAYYY
how do you like this?
This is a bad idea that will make understanding and debugging your program much harder.
You can use what in Python is called "monkey-patching" to achieve this:
(function() {
{
var origSomeFunction = someFunction;
someFunction = (function() {
x();
return origSomeFunction.apply(this, arguments);
});
}();
This works because I changed the (global) name someFunction to refer to a new function that I defined. Within the closure of that function I keep a reference to the original function that you want to pass the call on to.
In my opinion, event binding is more flexible than function wrapping since you can remove x whenever you want. Here is a possible implementation:
// Observable
var Observable = {};
Observable.create = function (options) {
var observable = { events: {} };
var events = options.events || [];
var i, l = events.length;
for (i = 0; i < l; i++) {
observable.events[events[i]] = [];
}
return observable;
};
Observable.one = function (observable, event, handler) {
Observable.on(observable, event, function f () {
Observable.un(observable, event, f);
handler.apply(this, arguments);
});
};
Observable.on = function (observable, event, handler) {
observable.events[event].push(handler);
};
Observable.un = function (observable, event, handler) {
observable.events[event].splice(
observable.events[event].indexOf(handler), 1
);
};
Observable.emit = function (observable, event, params) {
var handlers = observable.events[event];
var i, l = handlers.length;
if (!params) params = {};
params.source = observable;
for (i = 0; i < l; i++) {
handlers[i].call(observable, params);
}
};
Observable.observeMethod = function (observable, name) {
var meth = observable[name];
var before = 'before' + name.toLowerCase();
var after = 'after' + name.toLowerCase();
observable.events[before] = [];
observable.events[after] = [];
observable[name] = function () {
var ret;
Observable.emit(observable, before);
ret = meth.apply(observable, arguments);
Observable.emit(observable, after, { value: ret });
return ret;
};
};
// init
var printer = init({
sayHello: function () {
this.print('Hello World.');
},
sayHi: function (e) {
this.print('Hi ' + e.pseudo + '.');
},
print: function (msg) {
print(msg);
}
});
var clock = init({
tid: null,
events: ['tick'],
stop: function () {
clearTimeout(this.tid);
},
start: function () {
var me = this;
var time = 0;
clearTimeout(this.tid);
(function tick () {
me.tid = setTimeout(tick, 1000);
me.emit('tick', { time: time++ });
})();
}
});
// demo: printer
printer.on('afterprint', printNewline);
printer.on('beforesayhello', printBullet);
printer.sayHello();
printer.sayHello();
printer.un('beforesayhello', printBullet);
printer.sayHello();
// demo: clock
clock.on('tick', function (e) {
if (e.time) printer.print('tick ' + e.time);
if (e.time === 3) this.stop();
});
clock.one('afterstop', clock.start);
clock.start();
// helpers
function init (obj) {
obj = initObservable(obj);
obj.one = function (event, handler) {
Observable.one(this, event, handler);
};
obj.on = function (event, handler) {
Observable.on(this, event, handler);
};
obj.un = function (event, handler) {
Observable.un(this, event, handler);
};
obj.emit = function (event, params) {
Observable.emit(this, event, params);
};
return obj;
}
function initObservable (obj) {
var k, observable;
observable = Observable.create({
events: obj.events
});
for (k in observable) {
obj[k] = observable[k];
}
for (k in obj) {
if (typeof obj[k] === 'function') {
Observable.observeMethod(obj, k);
}
}
return obj;
}
function printBullet () {
print('• ');
}
function printNewline () {
print('<br />');
}
function print (html) {
document.body.innerHTML += html;
}

Why are my properties assigning incorrectly?

I created an ObservablePropertyList which is supposed to execute a callback when a property changes. The implementation is:
function ObservablePropertyList(nameCallbackCollection) {
var propertyList = {};
for (var index in nameCallbackCollection) {
var private_value = {};
propertyList["get_" + index] = function () { return private_value; }
propertyList["set_" + index] = function (value) {
// Set the value
private_value = value;
// Invoke the callback
nameCallbackCollection[index](value);
}
}
return propertyList;
}
And here's a quick test demonstration:
var boundProperties = BoundPropertyList({
TheTime: function (value) {
$('#thetime').text(value);
},
TheDate: function (value) {
$('#thedate').text(value);
}
});
var number = 0;
setInterval(function () {
boundProperties.set_TheTime(new Date());
boundProperties.set_TheDate(number++);
}, 500);
For some reason though, the properties are not being assigned correctly or something. That is, calling set_TheTime for some reason executes the callback for set_TheDate, almost as though it were binding everything to only the last item in the list. I can't for the life of me figure out what I'm doing wrong.
When using loops like that you need to wrap it in an enclosure
function ObservablePropertyList(nameCallbackCollection) {
var propertyList = {};
for (var index in nameCallbackCollection) {
(function(target){
var private_value = {};
propertyList["get_" + index] = function () { return private_value; }
propertyList["set_" + index] = function (value) {
// Set the value
private_value = value;
// Invoke the callback
target(value);
}
})(nameCallbackCollection[index]);
}
return propertyList;
}
You need to create a closure in order for each iteration of the for loop to have its own private_variable object. Otherwise, each iteration just overwrites the previous (since private_variable is hoisted to the top of its scope). I'd set it up like this:
var ObservablePropertyList = (function () {
"use strict";
var handleAccess = function (propList, key, callback) {
var privValue = {};
propList["get_" + key] = function () {
return privValue;
};
propList["set_" + key] = function (value) {
// Set the value
privValue = value;
// Invoke the callback
callback(value);
};
};
return function (coll) {
var propertyList = {}, index;
for (index in coll) {
handleAccess(propertyList, index, coll[index]);
}
return propertyList;
};
}());
var boundProperties = ObservablePropertyList({
TheTime: function (value) {
$('#thetime').text(value);
},
TheDate: function (value) {
$('#thedate').text(value);
}
}), number = 0;
setInterval(function () {
boundProperties.set_TheTime(new Date());
boundProperties.set_TheDate(number++);
}, 500);
DEMO: http://jsfiddle.net/PXHDT/

how to call function using name such as "function someName(){}"?

I have a name of a private function in JavaScript as a string, how do I call that function?
var test = function () {
this.callFunction = function(index) {
return this["func" + index]();
}
function func1() { }
function func2() { }
...
function funcN() { }
}
var obj = new test();
obj.callFunction(1);
func1 and friends are local variables, not members of the object. You can't call them like that (at least not in any sane way).
Define them with function expressions (instead of function declarations) and store them in an array.
var test = function () {
this.callFunction = function(index) {
return funcs[index]();
}
var funcs = [
function () {},
function () {},
function () {}
];
}
var obj = new test();
obj.callFunction(0);
As your code stands, the functions are not present as properties of the instance. What you need to do is create them as properties of the context.
var test = function () {
this.callFunction = function(index) {
return this["func" + index];
}
this.func1 = function() { }
this.func2 = function() { }
...
}
var obj = new test();
obj.callFunction(1)();
you can use eval
var test = function () {
this.callFunction = function(index) {
return eval("func" + index + '()');
}
function func1() {
return 1;
}
function func2() {
return 2;
}
function funcN() { }
};
var obj = new test();
obj.callFunction(2);
eval is evil
You can use a private array of functions:
var test = function() {
var func = [
function() { return "one" },
function() { return "two"; }
]
this.callFunction = function(index) {
return func[index]();
}
}
var obj = new test();
var ret = obj.callFunction(1);
console.log(ret);​
​
http://jsfiddle.net/V8FaJ/

async memoized - understanding source code

From async.memoize(), what does the last else block after the comment in this function do?
https://github.com/caolan/async/blob/master/lib/async.js#L671
async.memoize = function (fn, hasher) {
var memo = {};
var queues = {};
hasher = hasher || function (x) {
return x;
};
var memoized = function () {
var args = Array.prototype.slice.call(arguments);
var callback = args.pop();
var key = hasher.apply(null, args);
if (key in memo) {
callback.apply(null, memo[key]);
}
else if (key in queues) {
queues[key].push(callback);
}
else {
// what does this else block do?
queues[key] = [callback];
fn.apply(null, args.concat([function () {
memo[key] = arguments;
var q = queues[key];
delete queues[key];
for (var i = 0, l = q.length; i < l; i++) {
q[i].apply(null, arguments);
}
}]));
}
};
memoized.unmemoized = fn;
return memoized;
};
If the key is not found in either the memo or the queues objects (the first two parts of the if statement), then it calls the callback and assigns the return value from the callback to queues[key] as a one element array.
Then, it calls whatever functions where in the queue[key] array.

Categories

Resources