简体   繁体   中英

Why Javascript functions don't work in the coded order?

I'm making a studying timer for the Pomodoro technique (25 min studying 5 min breaking). My timer works only when I called it once. If I call it twice or more, it count down to negative minutes and seconds. Moreover, when I called the studying timer first and the breaking timer later, it executes the breaking timer and skips the studying timer.

let timer;
function studying(){
    display_quote();
    var min = document.getElementById("study-min").value;
    document.getElementById("state").innerHTML = "STUDYING";
    var sec = min*60;
    timer = setInterval(function(){
        minn = Math.floor(sec/60);
        secc = sec%60;
        document.getElementById("clock").innerHTML = getTime(minn,secc);
        sec-=1;
        if(sec==-1){
            clearInterval(timer);
            return;
        }
    },1000)
}
function breaking(){
    display_quote();
    min = document.getElementById("break-min").value;
    document.getElementById("state").innerHTML = "BREAKING";
    sec = min*60;
    timer = setInterval(function(){
        minn = Math.floor(sec/60);
        secc = sec%60;
        document.getElementById("clock").innerHTML = getTime(minn,secc);
        sec-=1;
        if(sec==-1){
            clearInterval(timer);
            return;
        }
    },1000)
}

and here is the looping

for(var t=1;t<=loop;t++){
        studying();
        breaking();
    }

That happens because callbacks inside setInterval are running "asynchronously", to solve this you could use Promises along with Async/Await . You could have a sweet code like this:

let timer;

async function studying() {
    display_quote();
    let promise = new Promise((resolve, reject) => {
        var min = document.getElementById("study-min").value;
        document.getElementById("state").innerHTML = "STUDYING";
        var sec = min * 60;
        timer = setInterval(function () {
            minn = Math.floor(sec / 60);
            secc = sec % 60;
            document.getElementById("clock").innerHTML = getTime(minn, secc);
            sec -= 1;
            if (sec == -1) {
                clearInterval(timer);
                resolve();
                return;
            }
        }, 1000);
    });

    return promise;
}

async function breaking() {
    display_quote();
    let promise = new Promise((resolve, reject) => {
        min = document.getElementById("break-min").value;
        document.getElementById("state").innerHTML = "BREAKING";
        sec = min * 60;
        timer = setInterval(function () {
            minn = Math.floor(sec / 60);
            secc = sec % 60;
            document.getElementById("clock").innerHTML = getTime(minn, secc);
            sec -= 1;
            if (sec == -1) {
                clearInterval(timer);
                resolve();
                return;
            }
        }, 1000);
    });

    return promise;
}

async function doJob() {
    let loop = 5;
    for (var t = 1; t <= loop; t++) {
        await studying();
        await breaking();
    }
}

doJob();

This time studying() is going to execute first and then breaking() in that order.

The magic here is done by await which basically means: "wait here until any asynchronous process inside studying() is complete", and resolve() : which indicates that the asynchronous process is complete and the control should be returned outside studying()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM