Javascript Asynchronous to Synchronous task - javascript

I have the following code (these codes are in separated js files ) :
Code 1 (home.js):
alert('1');
BeginGetDashboardsMethod();
alert('5');
Code 2(script.js) :
function BeginGetDashboardsMethod(){
var stop = 'false';
alert('2');
try {
Service.GetDashboardsMobile("" + curr_cod_user, SuccessGetDashboardMethod, ErrorGetDashboardMethod);
}
catch (e) {
}
function SuccessGetDashboardMethod(result) {
alert('3');
json = result;
json = JSON.parse(json);
ListDashboards(json);
}
function ErrorGetDashboardMethod(err) {
alert(JSON.stringify(err));
}
function ListDashboards(json) {
alert('4');
for (var i = 0; i < json.Dashboards.length; i++) {
if (json.Dashboards.length === 1)
Items = "[{key:\'" + json.Dashboards[i].OBV_ST_TITULO + "\', title:\'" + json.Dashboards[i].OBV_ST_TITULO + "\'}]";
else {
if (i == 0) {
Items += "[{key:\'" + json.Dashboards[i].OBV_ST_TITULO + "\', title:\'" + json.Dashboards[i].OBV_ST_TITULO + "\'} ";
}
else if (i + 1 == json.Dashboards.length) {
Items += ",{key:\'" + json.Dashboards[i].OBV_ST_TITULO + "\', title:\'" + json.Dashboards[i].OBV_ST_TITULO + "\'}] ";
}
else {
Items += ",{key:\'" + json.Dashboards[i].OBV_ST_TITULO + "\', title:\'" + json.Dashboards[i].OBV_ST_TITULO + "\'} ";
}
}
}
obj = eval(Items);
} }
My code works asynchronous. After Service.GetDashboardsMobile call the code "skip" Success callback and execute alert(5); while executing callback. Is there a way to make that functions synchronous?
To be more exactly, I want that sequence : alert('1');-->alert('2');-->alert('3');-->alert('4');-->alert('5')

Welcome to the new world of Promises.
script.js
alert("1"); // script 1 loaded
function $dashboard(user) {
function getDashboard(start, limit) {
var user = user;
return new Promise(function(pass, fail) {
if( Math.random()*3 > 2 ) {
fail(new Error("boo hoo"));
} else {
window.setTimeout(pass, 5000, '{"time": 5000, "content": "foo"}');
}
});
}
function parseData(json) {
return new Promise(function(pass, fail) {
try {
pass(JSON.parse(json));
} catch(e) {
fail(e);
}
});
}
function printData(data) {
alert(JSON.stringify(data));
return true;
}
return {
get: getDashboard,
parse: parseData,
print: printData
};
}
home.js
(function(d,w,$) {
alert("2"); // script 2
var dashboard = $("mcfoobar");
dashboard
.get(0, 100)
.then(function(sData) {
alert("3"); // data retrieved
return dashboard.parse(sData);
})
.then(function(oData) {
alert("4"); // data parsed
return dashboard.print(oData);
})
.then(function(result) {
alert("5"); // data printed
})
.catch(function(err) {
alert(JSON.stringify(err)); // Something went wrong
});
}(document, window, $dashboard));
Notes:
Why all the alerts? Surely console.log(..) is a much better solution. Certainly a lot less clicking.
You will have to make sure script.js is loaded. Hopefully home.js has some sort of el.onload event on the <script> element of script.js.
For backward compatibility you will need to have a definition of Promises just in case. But that should be easy to implement. You can use v8 version if it doesn't already exist in some compatibility library.
Make sure you note how values are changed in the chain by returning different values in the .then() function. To keep original values simply forward parameters.

Related

Javascript - continue foreach

I have a piece of code:
var a = false;
function wait(milliseconds, async) {
if(!async) {
setTimeout(function() {
console.log('Sync timer done.');
a = true;
return true;
}, milliseconds*1000);
}
(...)
f_recipe.forEach(function(item, index) {
if (obj['actual_step'] != 0 && obj['actual_step'] != index ) {
e = "Desync";
throw e;
};
console.log("Step: " + obj.actual_step);
if(item.substr(item.length - 6) != "false)"){
if (eval(item)) {
obj['actual_step']++;
}
} else {
eval(item);
var ival = setInterval(function(){
if(a) {
console.log('do the next thing');
clearInterval(ival);
}
}, 1000);
}
});
But when I get to 'do the next thing'(interval complete), the forEach loop doesn't continue to the next element of the array. 'a' is set to true after timeout (kind of a synchronous wait in JS). f_recipes is a string array with function call (e.g. 'wait(20, false)').
How to get it to work?
What you're trying to do seems like a very bad idea, but promises can help with this (using Bluebird here because it provides Promise.delay and Promise.each):
function wait(seconds, dontActuallyWait) {
return dontActuallyWait ? null : Promise.delay(seconds * 1000);
}
function runSequence(things) {
return Promise.each(things, function(thing) {
return eval(thing);
});
}
runSequence([
'console.log("hello")',
'wait(2, false)',
'console.log("hello again")',
'wait(5, false)',
'console.log("goodbye")'
]);
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.5.1/bluebird.min.js"></script>

javascript variable showing as undefined in Elevator Saga learning tool

I'm new to JavaScript, coming over from Swift. Trying it out code-learning challenges at http://play.elevatorsaga.com/
and some behavior is tough to grasp. In the following code, I setup floor & elevator objects. I am trying to get the elevator to get the floor it is about to pass's button request (if someone has pressed that floor's up or down button to call the elevator)
- in the code console.log(" (x) passing_floor - Same direction requested");
However the logs I get tell me that the up/downRequests are undefined
passing_floor 2 up
upRequest: undefined
downRequest: undefined
Is the issue with initialization? scoping? What is the proper way to achieve what I am trying to do?
{
init: function(elevators, floors) {
function initializeElevator(elevator){
elevator.on("floor_button_pressed", function(floorNum) {
elevator.goToFloor(floorNum);
});
elevator.on("idle", function() {
elevator.goToFloor(0);
});
elevator.on("passing_floor", function(floorNum, direction) {
if ((floorNum.upRequest) && (direction =='up')) {
floorNum.upRequest = false;
console.log(" (x) passing_floor - Same direction requested");
} else if ((floorNum.downRequest) && (direction == 'down')) {
floorNum.downRequest = false;
console.log(" (x) passing_floor - Same direction requested");
} else {
console.log("passing_floor " + floorNum + " " + direction);
console.log("upRequest: " + floorNum.upRequest);
console.log("downRequest: " + floorNum.downRequest);
}
});
}
function initializeFloor(floor){
var upRequest = false;
var downRequest = false;
floor.on("up_button_pressed", function() {
this.upRequest = true;
});
floor.on("down_button_pressed", function() {
this.downRequest = true;
});
}
elevators.forEach(initializeElevator);
floors.forEach(initializeFloor);
},
update: function(dt, elevators, floors) { }
}
Thank you for taking the time to help me understand Javascript a bit more, trying out W3School to get around it, but let me know if you have better sites I should look at..
I was able to proceed with the desired behavior by creating an "array" of floors that were global - I'm not sure if this was a scoping issue or something else though!
{
init: function(elevators, floors) {
var floorArray = new Array(floors.length);
var elevatorOnFloor = new Array(floors.length);
//the init function populates the listeners for the elevator objects
function initializeElevator(elevator){
elevator.on("floor_button_pressed", function(floorNum) {
elevator.goToFloor(floorNum, true);
});
elevator.on("idle", function() {
elevator.goToFloor(0);
});
elevator.on("passing_floor", function(floorNum, direction) {
if ((floorArray[floorNum] == 1) && (direction =='up')) {
floorArray[floorNum] = 0;
elevator.goToFloor(floorNum, true);
console.log("picking someone else going UP");
elevatorOnFloor[floorNum]+=1;
console.log("elevators per floor:"+ elevatorOnFloor );
} else if ((floorArray[floorNum] = 2) && (direction == 'down')) {
floorArray[floorNum] = 0;
elevator.goToFloor(floorNum, true);
console.log("picking someone else going DOWN");
elevatorOnFloor[floorNum]-=1;
console.log("elevators per floor:" + elevatorOnFloor + floorArray );
} else {
console.log("passing_floor " + floorNum + " " + direction);
if (direction =='up') {
elevatorOnFloor[floorNum]+=1;
} else {
elevatorOnFloor[floorNum]-=1;
}
}
});
}
function initializeFloor(floor){
floor.on("up_button_pressed", function() {
floorArray[floor] = 1;
});
floor.on("down_button_pressed", function() {
floorArray[floor] = 2;
});
}
function initializeElevatorsOnFloor(floor){
elevatorOnFloor[floor] = 0;
}
// we initialize all the elevators
elevators.forEach(initializeElevator);
// initialize the floors
floors.forEach(initializeFloor);
floors.forEach(initializeElevatorsOnFloor);
},
update: function(dt, elevators, floors) {
// We normally don't need to do anything here
}
}

asynchronous execution in protractor end to end tests

I have written a function , which is returning a value. In my main i am calling the function like this:
var fn_return_val = lesson.select_lesson(lesson1_text);
console.log("returned value is : " + fn_return_val);
And my function implementation is like(other file.js) :
module.exports = {
select_lesson:
function select_lesson(lesson_name) {
console.log('\n ************************* Lessson name: ' + lesson_name);
var desiredOption, status;
var repeter = element.all(by.repeater('item in items'));
repeter.then(function (items) {
items.forEach(function (icon) {
console.log('\n ************************* item');
icon.getText().then(function (txt) {
if (txt == lesson_name) {
desiredOption = icon;
}
})
}).then(function clickOption() {
if (desiredOption) {
var el = desiredOption.all(by.css('[ng-click="launchActivity()"]'));
var el_progress = desiredOption.all(by.css('.pna-progress'));
var abc = el.getAttribute('value').then(function (txt) {
status = txt;
return status
});
el_progress.getAttribute('style').then(function (progress) {
console.log('\n ************************* Lessson progress : ' + progress);
});
el.click();
}
});
});
}
};
The problem is function is returning "undefined" value, and the print statement console.log("returned value is : " + fn_return_val);
is executing before the function implementation
Can anyone help me on resolving this?
This is all about promises and protractor's Control Flow.
You need to resolve the promise and log the results inside then:
lesson.select_lesson(lesson1_text).then(function(fn_return_val) {
console.log("returned value is : " + fn_return_val);
});
And you also need to return from a function:
function select_lesson(lesson_name) {
...
// return here
return repeter.then(function (items) {
...
}).then(function clickOption() {
...
});
});
}

JS Wait till page Loads, Unless 5 seconds have passed then start timer (alter current .js)

The below code is a timer for my site's ads. The way its setup now it waits for the page to load fully before starting the timer. What I would like to do is to Alter this slightly to only wait 5 seconds, if the page has not finished loading by then just go ahead and start the timer. I have no idea how to do this at all.
$(document).ready(function () {
ptcevolution_surfer();
});
function showadbar(error) {
$("#pgl").removeAttr("onload");
if (error == '') {
$(".adwait").fadeOut(1000, function () {
$("#surfbar").html('<div class="progressbar" id="progress"><div id="progressbar"></div></div>');
$("#progressbar").link2progress(secs, function () {
endprogress('');
});
});
} else {
$(".adwait").fadeOut(1000, function () {
$("#surfbar").html("<div class='errorbox'>" + error + "</div>");
$(".errorbox").fadeIn(1000);
});
}
}
/* End Surf Bar */
function endprogress(masterkey) {
if (masterkey == '') {
$("#surfbar").fadeOut('slow', function () {
$("#vnumbers").fadeIn('slow');
});
return false;
} else {
$("#vnumbers").fadeOut('slow', function () {
$(this).remove();
$("#surfbar").fadeIn('slow');
});
}
$("#surfbar").html("Please wait...");
var dataString = 'action=validate&t=' + adtk + '&masterkey=' + masterkey;
$.ajax({
type: "POST",
url: "index.php?view=surfer&",
data: dataString,
success: function (msg) {
if (msg == 'ok') {
$("#surfbar").html("<div class='successbox'>" + adcredited + "</div>");
$(".successbox").fadeIn('slow');
if (adtk == 'YWRtaW5hZHZlcnRpc2VtZW50') {
window.opener.hideAdminAdvertisement();
} else {
window.opener.hideAdvertisement(adtk);
}
return false;
} else {
$("#surfbar").html("<div class='errorbox'>" + msg + "</div>");
$(".errorbox").fadeIn('slow');
}
}
});
}
function ptcevolution_surfer() {
if (top != self) {
try {
top.location = self.location;
} catch (err) {
self.location = '/FrameDenied.aspx';
}
}
$("#surfbar").html("<div class='adwait'>" + adwait + "</div>");
}
By your use of $, I'm going to assume jQuery
var __init = (function () {
var initialised = 0; // set a flag, I've hidden this inside scope
return function () { // initialisation function
if (initialised) return; // do nothing if initialised
initialised = 1; // set initialised flag
ptcevolution_surfer(); // do whatever
};
}()); // self-invocation generates the function with scoped var
window.setTimeout(__init, 5e3); // 5 seconds
$(__init); // on page ready
Now what happens? The first time the function is fired, it prevents itself from being fired a second time, then starts off whatever you want done.

Unexpected } tokens in js - trying to learn ajax

I'm just trying to learn some ajax so I wrote some code for basically an address book to pull some data. My javascript is rubbish but I cannot seem to understand what I am doing wrong, the error points to function ajaxCall but I see no issue with that function either:
(function () {
var searchForm = document.getElementById("search-form"),
searchField = document.getElementById("q"),
getAllButton = document.getElementById("get-all"),
target = document.getElementById("output");
var addr = {
search: function (event) {
var output = document.getElementById("output");
//start ajax call
ajaxCall("data/contacts.json", output, function (data) {
var searchValue = searchField.value,
addrBook = data.addressBook,
count = addrBook.length,
i;
//stop default behavior
event.preventDefault();
//clear target
target.innerHTML = "";
if (count > 0 && searchValue !== "") {
for (i = 0; i < count; i++) {
var obj = addrBook[i],
isItFound = obj.name.indexOf(searchValue);
if (isItFound !== -1) {
target.innerHTML += '<p>' + obj.name + ', ' + obj.email + '<p>';
} //end if isItFound
} //end for loop
} //end if count check
}); //end ajax call
}, //end method search
getAllContacts: function () {
var output = document.getElementById("output");
ajaxCall("data/contacts.json", output, function (data) {
var addrBook = data.addressBook,
count = addrBook.length,
i;
target.innerHTML = "";
if (count > 0) {
for (i = 0; i < count; i++) {
var obj = addrBook[i];
target.innerHTML += '<p>' + obj.name + ', ' + obj.email + '<p>';
} //end for loop
} //end if
}); //end ajax call
}, //end method getAllContacts
setActiveSection: function () {
this.parentNode.setAttribute("class", "active");
}, //end method setActiveSection
removeActiveSection: function () {
this.parentNode.removeAttribute("class");
}, //end method removeActiveSection
addHoverClass: function () {
searchForm.setAttribute("class", "hovering");
}, //end method addHoverClass
removeHoverClass: function () {
searchForm.removeAttribute("class");
} //end method removeHoverClass
} //end addr object
searchField.addEventListener("keyup", addr.search, false);
searchField.addEventListener("focus", addr.addActiveSection, false);
searchField.addEventListener("blur", addr.removeActiveSection, false);
getAllButton.addEventListener("click", addr.getAllContacts, false);
searchForm.addEventListener("submit", addr.search, false);
searchForm.addEventListener("mouseover", addr.addHoverClass, false);
searchForm.addEventListener("mouseout", addr.removeHoverClass, false);
})(); //end anon function
function getHTTPObject() {
var xhr;
//in most cases this first if is executed
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
//otherwise support crappy IE6 and below
else if (window.ActiveXObject) {
xhr = new ActiveXObject("Msxml2.XMLHTTP");
}
return xhr;
}
function ajaxCall(dataUrl, outputElement, callback) {
//get ajax object
var request = getHTTPObject();
outputElement.innerHTML = "Loading...";
request.onreadystatechange = function () {
if (request.readyState === 4 && request.status === 200) {
//good ajax response..now save it
var contacts = JSON.parse(request.responseText);
if (typeof callback === "function")
callback(contacts);
} //end upper if
} //end onreadystatechange
request.open("GET", dataUrl, true);
request.send(null);
}
The javascript development tools keeps giving me an unexpected token } on line 97 but that changes all so often. Am I missing a curly brace somewhere?
I did put your code to this fiddle and fixed the errors as far as i can.
You missed some curly braces and semicolons. Also, you used ajaxCall() and getHTTPObject() before they were declared. Check it out. Unfortunately, i dont know if the problem is already fixed, but now the code is valid at least :)
Btw: (in my opinion) such long Code-Samples are always better pasted into a fiddle. Not only because you can focus on the probably messy code here while referring to the complete code sample somewhere else, also because you can make sure that there are no syntax-errors as you can quickly validate you code using jsLint before asking the question here.
You must re-check what your JSON response is, in console, and see if it is invalid.
Because at that very 97 line you say that you are parsing a response.

Categories