Meteor: Synchronous method - javascript

I'm failing to run a method on the server side synchronously, meaning to wait for it to be done.
mymethod: function(par1, par2){
var timer = Meteor.setTimeout(function() {
//do something
});
}
I tried to use Meteor.wrapAsync without success, whether I wrap the timer or the entire method like this:
Meteor.wrapAsync(Meteor.call('mymethod', par1, par2));

Weird.
if (Meteor.isServer) {
Meteor.methods({
mymethod: function(par1, par2) {
var timer = Meteor.setTimeout(function() {
console.log("Hey!");
}, 1000);
}
});
Meteor.call('mymethod', 'par1', 'par2');
}
works fine here in a newly created 0.9.3.1 app.

Related

How to test window.location in Jasmine

In my app that uses backbone I have the following function:
handleModelSaved: function () {
var redirect_location = 'redirect_path';
App.Messenger.success('Report was saved successfully!');
setTimeout(function () {
window.location = redirect_location;
}, 2000);
}
For now I have the following test:
describe('handleModelSaved', function () {
beforeEach(function () {
view = initV3View();
spyOn(App.Messenger, 'success');
view.handleModelSaved();
});
it("sends a success message", function () {
expect(App.Messenger.success).toHaveBeenCalledWith('Report was saved successfully!');
});
});
And my question is, how can I test with Jasmine this code:
setTimeout(function () {
window.location = redirect_location;
}, 2000);
You can just check the location property on the window object to have a specific value. Of course, you can only do this after the timeout has exprired. What you probably want to do is to override the setTimeout function with your own implementation that calls the specified callback function immediately. With that you can also check whether or not the setTimeout was called with the expected timeout. You can do this yourself or use Jasmine's Clock functions to mock the native timeout functions: http://jasmine.github.io/2.0/introduction.html
Another option is to use the done function that is passed as an argument to your it() function callback. Which makes the test asynchronous.

Delete global variables nodejs

So I have a node app that when it's started makes an object.
function my_object(){
}
my_object.prototype.say_lol = function() {
setTimeout(function(){
console.log('lol');
}, 1000);
};
var ping = new my_object();
ping.say_lol();
process.on( 'SIGINT', function() {
delete global.ping; // Please?
// pseudo code to go update something in the database or whatever
setTimeout(function(){
process.exit();
}, 4000);
});
When it ends I need to delete that object to prevent it from firing lol over and over while the timeout is pending. Is there any elegant way of doing this?
You need to capture the id of what setTimeOut returns and then clear it if you don't want to fire at a later point.
my_object.prototype.say_lol = function() {
return (setTimeout(function(){
console.log('lol');
}, 1000));
};
var ping = new my_object();
var timeOutId = ping.say_lol();
process.on( 'SIGINT', function() {
clearTimeout(timeOutId);
process.exit();
});
If the event is not fired yet, it will be cancelled. If its already fired, it fails silenty.
I don't know of a way to stop the callback from firing. My approach would be to keep track of ping's state in another variable and use an if statement wrapping whatever chunk of code fires the unwanted callbacks.
function my_object(){ };
var stillHere = true;
my_object.prototype.say_lol = function() {
setTimeout(function(){
if(stillHere){
console.log('lol');
}
}, 2000);
};
var ping = new my_object();
ping.say_lol();
process.on( 'SIGINT', function() {
delete global.ping; // Please?
stillHere = false;
setTimeout(function(){
process.exit();
}, 4000);
});
Although I understand it's not a true answer, but this solved my issue. I ran the node process in a cluster and killed off any children that I wanted to delete. This worked in my instance as the children were performing endless tasks and when I needed them to be stopped that was the only logical way I could abort them.

My setTimeout doesn't respect the delay

I want to repeat a function every 10s with setTimeout. My function is:
dateInLive = function() {
crono = function(){
setTimeout(function() {
$('.datePoste').each(function(){
$(this).load('in_live.php','in_live='+$(this).attr('id'))
});
crono();
}
,10000);
}
crono();
}
But, it's really random; sometimes it's repeating after 15s, sometimes after 3s, sometimes after 6s.
Recall crono() only when all the ajax requests are completed :
function crono(){
setTimeout(function() {
var arr = [];
$('.datePoste').each(function(){
var self = this;
xhr = $.get('in_live.php', {in_live : this.id}, function(data) {
$(self).html( $.parseHTML(data) );
});
arr.push(xhr);
});
$.when.apply($, arr).done(crono);
}, 10000);
}
You're using setTimeout to run a repeated event.
This is correct (others have recommended setInterval instead, but there are issues with this).
However you aren't setting the timeout on the subsequent calls -- you're just calling the crono() function directly, so after the initial timeout delay, it will then just start calling itself immediately over and over and over forever (until it exhausts the stack space).
What you need to do is call setTimeout() each time you call the function. Recode it something like this:
dateInLive = function() {
crono = function(){
$('.datePoste').each(function(){
$(this).load('in_live.php','in_live='+$(this).attr('id'))
});
setTimeout(crono,10000);
}
setTimeout(crono,10000);
}
In this situation, i would use deferred objects.
function crono(){
setTimeout(function() {
var defArr = [];
$('.datePoste').each(function(i,el){
var deferred = $.Deferred();
defArr.push(deferred.promise());
$(this).load('in_live.php','in_live='+$(this).attr('id'), function() {
deferred.resolve();
});
});
$.when.apply($,defArr).done(crono);
}, 10000);
}
Doing it this way will request all sections, then when all sections are received, wait 10 seconds and request them again, avoiding the request from piling up in a slow network situation.
you are doing something before creating the new timeout, which means there is bound to be "some" delay.
have a look at the setInterval() function.
You just have the crono() function in the wrong place.
dateInLive = function() {
crono = function(){
setTimeout(function() {
crono();
$('.datePoste').each(function(){
$(this).load('in_live.php','in_live='+$(this).attr('id'))
});
}
,10000);
}
}

JavaScript/jQuery context - proxy?

I have to animate an element in an sync way (that is to wait until the animation (fadeIn() in this example) is completed, so I can propertly continue).
As fas as I know I have three options:
doSomething: function () {
$('.someElement').fadeIn(function () {
// do something else here...
});
}
Another approach (using $.proxy() to alter the context):
doSomething: function () {
$('.someElement').fadeIn($.proxy(function () {
this.doSomethingElse();
}, this));
},
doSomethingElse: function () {
// ...
}
However, since using $.proxy() kinda "mixes" the contexts and I really don't like this (because I just don't know when it'll come back and bite my ass off), I'm sometimes using this approach:
doSomething: function () {
$('.someElement').fadeIn(function () {
doSomethingElse();
});
function doSomethingElse () {
// ...
}
}
Now I'm wondering, is there any better approach? Something simpler and more elegant. Like:
doSomething: function () {
$('.someElement').fadeIn(function () {
// do this in an async way...
});
// simply do something else here...
}
This problem really bugs me, because I like clean code and I don't like this simple, yet un-clean solutions.
Create a mediatory variable to refer to your original object:
doSomething: function () {
var that = this;
$('.someElement').fadeIn(function() {
// use "that" here
});
}
If doSomethingElse() is another animation, you can chain and queue them mantaining the original context.

Implementing timeouts for node.js callbacks

This is a typical situation in node.js:
asyncFunction(arguments, callback);
When asynFunction completes, callback gets called. A problem I see with this pattern is that, if asyncFunction never completes (and asynFunction doesn't have a built-in time-out system) then callback will never be called. Worse, it seems that callback has no way of determining that asynFunction will never return.
I want to implement a "timeout" whereby if callback has not been called by asyncFunction within 1 second, then callback automatically gets called with the assumption that asynFunction has errored out. What is the standard way of doing this?
I'm not familiar with any libraries that do this, but it's not hard to wire up yourself.
// Setup the timeout handler
var timeoutProtect = setTimeout(function() {
// Clear the local timer variable, indicating the timeout has been triggered.
timeoutProtect = null;
// Execute the callback with an error argument.
callback({error:'async timed out'});
}, 5000);
// Call the async function
asyncFunction(arguments, function() {
// Proceed only if the timeout handler has not yet fired.
if (timeoutProtect) {
// Clear the scheduled timeout handler
clearTimeout(timeoutProtect);
// Run the real callback.
callback();
}
});
You probably need to come out with a solution of your own. Like
function callBackWithATimeout (callback, timeout) {
var run, timer;
run = function () {
if (timer) {
clearTimeout(timer);
timer = null;
callback.apply(this, arguments);
}
};
timer = setTimeout(run, timeout, "timeout");
return run;
}
and then
asyncFunction(arguments, callBackWithATimeout(callback, 2000));
You could do something like this:
function ensureExecution(func, timeout) {
var timer, run, called = false;
run = function() {
if(!called) {
clearTimeout(timer);
called = true;
func.apply(this, arguments);
}
};
timer = setTimeout(run, timeout);
return run;
}
Usage:
asyncFunction(arguments, ensureExecution(callback, 1000));
DEMO
But note the following:
The timeout is started immediately when you call ensureExecution, so you cannot cache that function reference.
The arguments passed to the callback will differ. For example asyncFunction might pass some arguments to callback upon success, but if the function is called by the timeout, no arguments will be passed. You have to keep that it mind. You could also provide default arguments with which the function should be called in this case:
function ensureExecution(func, timeout, args, this_obj) {
// ...
timer = setTimeout(function() {
run.apply(this_obj, args);
}, timeout);
//...
}
I ran into the same problem with a content script trying to open the port on the BG extension before the BG extension was ready. A work around was to wait for the BG extension to reply to a message and repeat this till successful. Here are the code snippets.
Content Script:
var nTimes = 10;
var bIsReady = false;
checkBGReady();
function checkBGReady() {
if (!bIsReady) {
chrome.runtime.sendMessage({msgText: "hello "+nTimes}, function(response) {
if (response && response.ack) {
console.log("have response:"+response.ack+" "+nTimes);
bIsReady = true;
// continue with initialization
bootStrap(sURL);
checkReady();
} else {
console.log("have no ack response %o",response);
}
});
}
nTimes -= 1;
if (nTimes > 0 && !bIsReady) {
setTimeout(checkBGReady,100);
}
}
BG Extension
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(sender.tab ?"from a content script:" + sender.tab.url :"from the extension");
if (request.msgText) {
console.log("Have msg "+request.msgText);
sendResponse({ack: "have contact "+request.msgText});
}
});
In my case it usually took after the first 100ms delay.

Categories

Resources