I am trying to build 'Simon Game' and used setTimeout method to lighten the buttons. when I write the the functions directly inside the setTimeout method it works.
$(function(){
var randPattern=[];
var buttonId=['red','yellow','green','blue'];
var origColor=['#B40404','#D7DF01','#0B610B','#0B0B61'];
var patternColor=['#F78181','#F4FA58','#A9BCF5','#81F781'];
var level= 5;
var count= 0;
var time= 1000;
$('#start').click(function gameStart() {
patternGenerate();
for(i=0; i<randPattern.length; i++){
display(i);
}
});
function patternGenerate() {
for(var h=0; h<level; h++){
randPattern.push( Math.floor( Math.random()*4) );
}
}
function display(i){
setTimeout(function(){document.getElementById(buttonId[randPattern[i]]).style.backgroundColor = patternColor[randPattern[i]];document.getElementById(randPattern[i]).play();}, 1500*i);
setTimeout(function(){document.getElementById(buttonId[randPattern[i]]).style.backgroundColor = origColor[randPattern[i]]}, 750+1500*i );
}
but when I write the functions that is going inside setTimeout method separately, such function a(i), and function b(i). It doesn't work. And the console says ''cannot read the property 'style' of null''. I think there is no difference between these two. I can't understand why the second way doesn't work while the first one does.
$(function(){
var randPattern=[];
var buttonId=['red','yellow','green','blue'];
var origColor=['#B40404','#D7DF01','#0B610B','#0B0B61'];
var patternColor=['#F78181','#F4FA58','#A9BCF5','#81F781'];
var level= 5;
var count= 0;
var time= 1000;
$('#start').click(function gameStart() {
patternGenerate();
for(i=0; i<randPattern.length; i++){
display(i);
}
});
function patternGenerate() {
for(var h=0; h<level; h++){
randPattern.push( Math.floor( Math.random()*4) );
}
}
function a (i){
document.getElementById(buttonId[randPattern[i]]).style.backgroundColor = patternColor[randPattern[i]];
document.getElementById(randPattern[i]).play();
}
function b (i){
document.getElementById(buttonId[randPattern[i]]).style.backgroundColor = origColor[randPattern[i]];
}
function display(i){
setTimeout(a,1500*i);
setTimeout(b,750+1500*i);
}
});
a and b expect to be passed an argument which will be assigned to i.
While you have a variable called i in the display function: You aren't passing it to a or b.
function display(i){
setTimeout( a, 1500*i, i );
setTimeout( b, 750+1500*i, i );
}
You are using an i inside function display(i){ but this variable is not passed to a or b. If you want to pass a variable, you still need to create a new closure and call your function from it:
function display(i){
setTimeout(function() { a(i) }, 1500*i);
setTimeout(function() { b(i) }, 750+1500*i);
}
Related
This question already has answers here:
How to access the correct `this` inside a callback
(13 answers)
Closed 5 years ago.
var delayTime = 2000;
for(var i = 0; i<this.textToWrite.length; i++){
setTimeout(
(
function (s){
return function () {
this.writeText += s;
console.log(this.writeText);
}
}(this.textToWrite[i])
), delayTime)
delayTime += 2000;
}
have some problem with this.writeText. It's global variable but when i even comment += s line then i have undefined value... (I set writeText: string = "" globaly) Is this.writeText reference to global variable? How can I access global variables in this example?
I need assing char from textToWrite object to writeText with 2s delay.
The problem can be that you used function word.
setTimeout(
((s) => {
return () => {
this.writeText += s;
console.log(this.writeText);
}
}(this.textToWrite[i])
), delayTime)
Another way is to use it without this if its global variable:
setTimeout(
((s) => {
return () => {
writeText += s;
console.log(this.writeText);
}
}(this.textToWrite[i])
), delayTime)
Only use arrow functions
settimeout(x => {
console.log(x);
}, 1000);
not like this and it will not accept out side parameters
settimeout(funtion(x) {
console.log(x);
}, 1000);
I have this code
it('This should pass anyway', function (done) {
testObj.testIt(regStr);
});
testObj
this.testIt = function (regStr) {
selector.count().then(function (orgCount) {
for (var curr = 0; curr < count; curr++) {
checkField(curr, regStr);
}
});
};
function checkField(curr, regStr) {
selector.get(curr).all(by.tagName('li')).get(0).getInnerHtml().then(function (text) {
expect(text).to.match(regStr, curr + '#ERR');
});
}
If one of these expects get a failure, test fails. How can i handle this? I mean - can i somehow count passed and failed expect()ations and return it? or, at least, dont let test break on first error.
I've tried try-catch, but nothing good happened.
it('This should pass anyway', function (done) {
try {
testObj.testIt(regStr);
} catch (e) {
console.log('#err' + e);
}
});
And then i wanted to use done(), but havent found any examples to do the similar. Can u please help me?
Sry for my english
UPD
You can return either null or a string from checkField(), join them up, and expect the array to be empty:
this.testIt = function (regStr) {
selector.count().then(function (orgCount) {
var errors = [];
for (var curr = 0; curr < orgCount; curr++) {
var e = checkField(curr, regStr);
if (e) { errors.push(e); }
}
assert.equal(0, errors.length, errors);
});
};
A cleaner approach would be to use map() to collect the data into an array:
var data = selector.map(function (elm) {
return elm.element(by.tagName('li')).getText();
});
expect(data).toEqual(["test1", "test2", "test3"]);
var arr = [1,2,3,4,5,6];
Array.prototype.filter2 = function(){
var fir = arguments[0];
var sec = arguments[1];
alert(fir);
alert(sec);
var arr2 = new Array();
for(var item=0; item<this.length;item++){
alert(this[item]); // 1 section
if(sec.call(this[item],fir)){
arr2.push(this[item]);
}
}
return arr2;
}
function xyz (ele ,x){
alert(x);
alert(ele);
return ele > x;
}
arr.filter2(2,xyz);
Till 1'st its running fine but while passing the argument to the callback... x is being alerted as "undefined" whereas ele = fir
Your answer is simple and straight:
either call your function normally,.. i.e
Array.prototype.filter2 = function(){
var fir = arguments[0];
var sec = arguments[1];
alert(fir);
alert(sec);
var arr2 = new Array();
for(var item=0; item<this.length;item++){
alert(this[item]); // 1 section
if(sec(this[item],fir)){
arr2.push(this[item]);
}
}
return arr2;
}
Or if you still want to stick with javascript .call(), then simply use it like this:
Array.prototype.filter2 = function(){
var fir = arguments[0];
var sec = arguments[1];
alert(fir);
alert(sec);
var arr2 = new Array();
for(var item=0; item<this.length;item++){
alert(this[item]); // 1 section
if(sec.call({},this[item],fir)){
arr2.push(this[item]);
}
}
return arr2;
}
call() and apply() are predefined JavaScript function methods. Both methods can be used to invoke a function, and both methods must have the owner object as first parameter.
You can read more about this by clicking here and find it under heading Invoking a Function with a Function Method
I am trying following lines of code to get a numeric value when condition is met
this.getMessageThreadsPosition = function (k, sub, callback) {
console.log(sub);
for(var i = 1; i <= k; i++){
commonsMethod.findElementDriver(that.messageSubjectTextPath(i)).then(function(foundelement){
foundelement.getText().then(function(text){
console.log(text);
if(text == sub){
callback(i);
}
});
});
}
};
But it seems that it never goes inside if condition.
For loop not waiting for winjs promise completion
for (var j = 0; j < magazineResult[0].data.length; j++) {
downRequest[0].data[j].COVER_PAGE_THUMB = parentUrl + eval(JSON.stringify(downRequest[0].data[j].COVER_PAGE_THUMB));
// Create a new download operation.
downloadFile(eval(magazineResult[0].data[j].COVER_PAGE_THUMB),eval(JSON.stringify(magazineResult[0].data[j].COVER_PAGE_THUMB)));
var url = downRequest[0].data[j].COVER_PAGE_THUMB;
var imgPath = downRequest[0].data[j].ISSUE_ID;
var imgExtension = url.substring(url.lastIndexOf('.') + 1);
var fileName = imgPath + "." + imgExtension;
var promise = Windows.Storage.ApplicationData.current.localFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting);
// Assign the completion handler function.
promise.done(function (newFile) {
MagazineDownLoad.downloadFile(url, fileName, j, newFile);
});
}
If you're trying to get MagazineDownLoad.downloadFile to operate asynchronously then you'll have to modify it's definition:
// in MagazineDownload
function downloadFile(url, filename, j, newfile){
return new WinJS.Promise(function (complete, error, progress) {
var returnValue;
//do the stuff that you do and assign something to returnValue
complete(returnValue);
});
}
Then you can use it asynchronously:
for (var j = 0; j < magazineResult[0].data.length; j++) {
downRequest[0].data[j].COVER_PAGE_THUMB = parentUrl + eval(JSON.stringify(downRequest[0].data[j].COVER_PAGE_THUMB));
// Create a new download operation.
downloadFile(eval(magazineResult[0].data[j].COVER_PAGE_THUMB),eval(JSON.stringify(magazineResult[0].data[j].COVER_PAGE_THUMB)));
var url = downRequest[0].data[j].COVER_PAGE_THUMB;
var imgPath = downRequest[0].data[j].ISSUE_ID;
var imgExtension = url.substring(url.lastIndexOf('.') + 1);
var fileName = imgPath + "." + imgExtension;
var promise = Windows.Storage.ApplicationData.current.localFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting);
// Assign the completion handler function.
promise.done(function (newFile) {
MagazineDownLoad.downloadFile(url, fileName, j, newFile).done(function(result){
//do some more stuff with the result
});
});
}
The WinJS.Promise() runs asynchronously and your for-loop runs in sync. What you are experiencing is expected. If you want to queue your actions you should not perform a loop, but rather queue a new action when your done() is called. Something like this:
var index = 0, data = magazineResult[0].data;
function queueDownload() {
// Duplicate all needed logic here from your question
var promise = Windows.Storage.ApplicationData.current.localFolder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting);
// Assign the completion handler function.
promise.done(function (newFile) {
MagazineDownLoad.downloadFile(url, fileName, j, newFile);
if (index < data.length) {
queueDownload(++index);
}
});
}
queueDownload(index);