This question already has answers here:
JavaScript Loop and wait for function
(2 answers)
Closed 2 years ago.
I want to stop this function for a few seconds while adding every digit,
but this function doesn't work as intended.
function yazmaeffetkti() {
var cumleler = ["salam necesen", "yaxsiyam sen "]
currentcumle = ""
for (var i = 0; i < cumleler.length; i++) {
cumle = cumleler[i]
for (var z = 0; z < cumle.length; z++) {
currentcumle += cumle[z]
function stateChange(currentcumle) {
setTimeout(function() {
console.log(currentcumle);
}, 3000);
}
stateChange(currentcumle)
}
currentcumle = ""
}
}
yazmaeffetkti()
The cleanest way to achieve that is to use async and await:
async function yazmaeffetkti() {
// ...
await new Promise(resolve => setTimeout(resolve, 3000));
console.log(currentcumle);
// ...
}
here is my version:
async function yazmaeffetkti() {
var cumleler = ["salam necesen", "yaxsiyam sen "]
currentcumle = ""
for (var i = 0; i < cumleler.length; i++) {
cumle = cumleler[i]
for (var z = 0; z < cumle.length; z++) {
currentcumle += cumle[z]
await stateChange(currentcumle)
}
currentcumle = ""
}
}
var stateChange = (currentcumle) => new Promise((resolve)=>{
setTimeout(function() {
console.log(currentcumle);
resolve(true);
}, 1000);
});
yazmaeffetkti()
In addition to Robo Robok's answer, here is an example using the same concept but with then instead of async/await. I personnaly prefer it but it's up to you.
function yazmaeffetkti() {
var cumleler = ["salam necesen", "yaxsiyam sen "]
currentcumle = ""
for (var i = 0; i < cumleler.length; i++) {
cumle = cumleler[i]
for (var z = 0; z < cumle.length; z++) {
currentcumle += cumle[z]
new Promise(resolve => setTimeout(resolve, 3000)).then(() => {
console.log(currentcumle);
});
}
currentcumle = ""
}
}
yazmaeffetkti()
Related
This is the code i got from codepen, it generates special characters and changes to the phrase i put, I'm wanting to compile this vanilla javascript code to react, because you can't use the DOM
there.
My real doubt is where do I put the useState so that it stops looping and shows character by character, this passing for example the state 'title' in a .
vanilla javascript code:
function setCharAt(str,index,chr) {
if(index > str.length-1) return str;
return str.substr(0,index) + chr + str.substr(index+1);
}
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=+<>,./?[{()}]!##$%^&*~`\|'.split('');
var progress404 = 0;
var total404 = $('.text__error').data('text').length;
var progressLink = 0;
var totalLink = $('.text__link a').data('text').length;
var scrambleInterval = setInterval(function() {
var string404 = $('.text__error').data('text');
var stringLink = $('.text__link a').data('text');
for(var i = 0; i < total404; i++) {
if(i >= progress404) {
string404 = setCharAt(string404, i, characters[Math.round(Math.random() * (characters.length - 1))]);
}
}
for(var i = 0; i < totalLink; i++) {
if(i >= progressLink) {
stringLink = setCharAt(stringLink, i, characters[Math.round(Math.random() * (characters.length - 1))]);
}
}
$('.text__error').text(string404);
$('.text__link a').text(stringLink);
}, 1000 / 60);
setTimeout(function() {
var revealInterval = setInterval(function() {
if(progress404 < total404) {
progress404++;
}else if(progressLink < totalLink) {
progressLink++;
}else{
clearInterval(revealInterval);
clearInterval(scrambleInterval);
}
}, 50);
}, 1000);
This is the code I developed to try to work:
const [ title, setTitle ] = useState('404 page not found')
const [ link, setLink ] = useState('click here to go home')
function setCharAt(str: string,index: number,chr: any) {
if(index > str.length-1) return str;
return str.substr(0,index) + chr + str.substr(index+1);
}
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-=+<>,./?[{()}]!##$%^&*~`\|'.split('');
var progress404 = 0;
var total404 = title.length
var progressLink = 0;
var totalLink = link.length
var scrambleInterval = setInterval(function() {
for(var i = 0; i < total404; i++) {
if(i >= progress404) {
setTitle( setCharAt(title, i, characters[Math.round(Math.random() * (characters.length - 1))]));
}
}
for(var i = 0; i < totalLink; i++) {
if(i >= progressLink) {
setLink( setCharAt(link, i, characters[Math.round(Math.random() * (characters.length - 1))]));
}
}
}, 1000 / 60);
setTimeout(function() {
var revealInterval = setInterval(function() {
if(progress404 < total404) {
progress404++;
}else if(progressLink < totalLink) {
progressLink++;
}else{
clearInterval(revealInterval);
clearInterval(scrambleInterval);
}
}, 50);
}, 1000);
Pls, help!
The function should print the letters "A" through "F" to the console, one letter per second.
The function works without setInterval/setTimeout.
// setInterval(alphabet, 1000, 'a', 'f');
function alphabet(from, to) {
var a = [], i = from.charCodeAt(0), j = to.charCodeAt(0);
for (; i <= j; ++i) {
setInterval(() => {
a.push(String.fromCharCode(i));
}, 1000);
}
// return console.log(a);
return a;
}
console.log(alphabet('a', 'f'));
You might wanna try this.
You can paste it on codepen
var a = [];
function alphabet(from, to) {
console.log(a);
setInterval(() => {
var i = from.charCodeAt(0);
var j = to.charCodeAt(0);
for (; i <= j; ++i) {
if(a.includes(String.fromCharCode(i))){
}else{
console.log(String.fromCharCode(i))
a.push(String.fromCharCode(i));
break;
}
}
}, 1000);
return a;
}
alphabet('a', 'f');
Here is a solution using an async sleep function.
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function alphabet(from,to){
var currentLetter = from[0];
while(currentLetter.charCodeAt(currentLetter[0]) != to.charCodeAt(to[0])+1){
let l = currentLetter
await sleep(1000)
console.log(l)
nextLetter = String.fromCharCode(currentLetter.charCodeAt(currentLetter[0])+1)
currentLetter = nextLetter;
}
}
alphabet('A','F');
function printLetters(start, finish) {
//should add checks here to validate start comes before finish
console.log(start)
if (start == finish) {
return
}
else {
setTimeout(printLetters, 1000, String.fromCharCode(start.charCodeAt(0)+1), finish)
}
}
printLetters('a', 'f')
An example of simple nested for loop:
for (let i=0; i<=2; i++) {
for (let j=0; j<=1; j++){
console.log("i is: " + i);
console.log("j is: " + j);
console.log("---");
}
}
Nested for loop with delay:
for (let i=0; i<=2; i++) {
for (let j=0; j<=1; j++){
task(i,j);
}
}
function task(i,j) {
setTimeout(function() {
console.log("i is: " + i);
console.log("j is: " + j);
console.log("---")
}, 1000 * i);
}
NOW MY QUESTION IS
How can I delay each loop seperately.
Current output (ignore the "---"):
i, j, delay, i, j, delay, ...
Desired output (ignore the "---"):
i, delay, j, delay, i, delay, j, delay ...
I tried things like below (but its returning a complete wrong output)
for (let i=0; i<=2; i++) {
for (let j=0; j<=1; j++){
taski(i);
taskj(j)
}
}
function taski(i) {
setTimeout(function() {
console.log("i is: " + i);
}, 1000 * i);
}
function taskj(j){
setTimeout(function() {
console.log("j is: " + j);
}, 1000 * j);
}
You could use Promise and async/await to handle sequential call
function taski(i) {
return new Promise(function (resolve) {
setTimeout(function () {
console.log("i is: " + i)
resolve()
}, 1000 * i)
})
}
function taskj(j) {
return new Promise(function (resolve) {
setTimeout(function () {
console.log("j is: " + j)
resolve()
}, 1000 * j)
})
}
async function execute() {
for (let i = 0; i <= 2; i++) {
for (let j = 0; j <= 1; j++) {
await taski(i)
console.log("delay")
await taskj(j)
console.log("delay")
}
}
}
execute()
Reference:
async function
Promise
Ok the thing is setTimeout works in it's own world that isn't limited by the for loops, or any other code for that matter, it doesn't actually "block" the current code at all, in the for loop you are just setting up a bunch of intervals, really fast one after the other (since the for loop doesn't stop or get delayed by the timeouts), which later execute in some unknown order when the time for each one individually runs out, which is not blocked or dependant on any of the other timeouts
If you want to keep relatively the same format you have now, but with delay blocking you can use await and promises and async functions
(async () =>
for (let i=0; i<=2; i++) {
for (let j=0; j<=1; j++){
await taski(i);
await taskj(j)
}
}
)()
function taski(i) {
return new Promise((rs) => setTimeout(function() {
res(console.log("i is: " + i));
}, 1000 * i));
}
function taskj(j){
return new Promise((rs) => setTimeout(function() {
res(console.log("j is: " + j)
}, 1000 * j));
}
You could try to to an asynchronous approach with async/await:
function sleep(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
(async function() {
for (let i = 0; i <= 2; i++) {
for (let j = 0; j <= 1; j++) {
await taski(i);
await taskj(j);
}
}
}())
async function taski(i) {
await sleep(1000 * i);
console.log("i is: " + i);
}
async function taskj(j) {
await sleep(1000 * j);
console.log("j is: " + j);
}
I am trying to use $.when apply in my code. However, it seems that the format return is different for single and multiple request. How can i cater for it?? I am trying not to have another if else outside of it.
$.when.apply(null, apiRequestList).then(function () {
for (var i = 0; i < arguments.length; i++) {
var value = arguments[0];
}
});
This is what i do not want to do.
if (apiRequestList.length === 1) {
$.ajax({
});
} else {
$.when.apply(null, apiRequestList).then(function () {
for (var i = 0; i < arguments.length; i++) {
var value = arguments[0];
}
});
}
You can simply convert arguments into an array, when the length of apiRequestList is 1:
$.when.apply(null, apiRequestList).then(function() {
var _arguments = Array.prototype.slice.call(arguments);
if (Array.isArray(apiRequestList) && apiRequestList.length === 1)
_arguments = [arguments];
for (var i = 0; i < _arguments.length; i++) {
var value = _arguments[i][0];
console.log(value);
}
});
Live Example on jsFiddle (since we can't do ajax on Stack Snippets):
function x(a) {
return $.post("/echo/html/", {
html: "a = " + a,
delay: Math.random()
});
}
function doIt(apiRequestList) {
$.when.apply(null, apiRequestList).then(function() {
var _arguments = arguments;
if (Array.isArray(apiRequestList) && apiRequestList.length === 1)
_arguments = [arguments];
for (var i = 0; i < _arguments.length; i++) {
var value = _arguments[i][0];
console.log(value);
}
console.log("----");
});
}
doIt([x(1), x(2), x(3)]);
doIt([x(4)]);
Example output (it'll vary because of the Math.random()):
a = 4
----
a = 1
a = 2
a = 3
----
Here is a program i'm trying wrap my head around with, how do i print the items in the q properly, once all the results are pushed ?
function asyncAdd(a,b,callback) {
setTimeout(function() {
return callback(a+b);
},0);
}
var q = [];
var ctr = 0;
for (var i=0; i<9; i++) {
(function(i) {
var res = asyncAdd(i, 0, printRes);
q.push(res);
})(i);
}
function done(q) {
console.log("done"+q);
}
function printRes(res) {
return res;
}
Please have a look at my version
function asyncAdd(a,b,callback) {
callback(a+b);
}
var q = [];
var ctr = 0;
var max = 9;
for (var i = 0; i < max; i++) {
asyncAdd(i, 0, printRes);
}
function done(q) {
console.log("done " + q);
}
function printRes(res) {
q.push(res);
if (q.length === max)
done(q);
}