繁体   English   中英

如何在每次函数调用之前等待setTimeout?

[英]How to wait for setTimeout before each function call?

我需要使用多个参数多次调用一个函数。 我希望在上一次调用的超时完成后调用它。 我尝试了以下方法,但它似乎没有正常工作。 这是JSFiddle )。

现在它只是在第一次通话后等待。 我知道这不是正确的方法,但我找不到任何正确显示如何做的例子。 我还需要将其转换为typescript ,所以请在回答时考虑一下。

<!DOCTYPE html>
<html>
<body>

<p>Click the button to wait 3 seconds, then alert "Hello".</p>

<button onclick="call()">Call all methods</button>

<script>
var myVar;

function call(){
myFunction('normal1','heading1','message1');
myFunction('normal2','heading2','message2');
myFunction('normal3','heading3','message3');

/*Output should be:
(first time dont wait)
heading1 message1
(then wait for timeout and remove the elements)
heading2 message2
(then wait for timeout and remove the elements)
heading3 message3
*/
}

function myFunction(msgType,heading,message) {
console.log(!!document.getElementById("snackbarParent"),document.getElementById('snackbarParent'));
    if(document.getElementById("snackbarParent") == null)
    {
        alertFunc(msgType,heading,message);
    }
    else{
        setTimeout(function(){
        let parent = document.getElementById('snackbarParent');
            parent.parentNode.removeChild(parent);
            alertFunc(msgType,heading,message);
        },3500);
    }
}

function alertFunc(msgType,heading,message) {

    let div = document.createElement('div');
        div.className = 'snackbarParent';
        div.id = "snackbarParent";
        div.innerHTML = '<div id="snackbar"><b style="color:' + msgType + '"> ' + heading + ' </b>' + message + '</div>';

        document.documentElement.appendChild(div);
        // Get the snackbar DIV
        let x = document.getElementById("snackbar");

        // Add the "show" class to DIV
        x.className = "show";
    setTimeout(function(){
        x.className = x.className.replace("show", "");
        alert("Should display "+heading+" "+message+" now!");
    }, 3000);

}
</script>

</body>
</html>

注意:

函数call()仅用于表示目的。 参数可以具有任何值,并且可以随时随地调用函数myFunction()。

由于这个问题用typescript标记,我打算假设在Typescript中写这个是一个选项。

在代码保持正常外观时,您可以使用async/await轻松实现所需的效果:

var myVar;

async function call(){
    await myFunction('normal1', 'heading1', 'message1');
    await myFunction('normal2', 'heading2', 'message2');
    await myFunction('normal3', 'heading3', 'message3');
}
function timeout(delay: number) {
    return new Promise(r => setTimeout(r, delay));
}
async function myFunction(msgType: string, heading: string, message: string) {
    console.log(!!document.getElementById("snackbarParent"), document.getElementById('snackbarParent'));
    if (document.getElementById("snackbarParent") == null) {
        await alertFunc(msgType, heading, message);
    }
    else {
        await timeout(3500);

        let parent = document.getElementById('snackbarParent');
        parent.parentNode.removeChild(parent);
        await alertFunc(msgType, heading, message);

    }
}

async function  alertFunc(msgType, heading, message) {

    let div = document.createElement('div');
    div.className = 'snackbarParent';
    div.id = "snackbarParent";
    div.innerHTML = '<div id="snackbar"><b style="color:' + msgType + '"> ' + heading + ' </b>' + message + '</div>';

    document.documentElement.appendChild(div);
    // Get the snackbar DIV
    let x = document.getElementById("snackbar");

    // Add the "show" class to DIV
    x.className = "show";
    await timeout(3000);
    x.className = x.className.replace("show", "");
    alert("Should display " + heading + " " + message + " now!");

}

注意 :如果你不想要打字稿,babel也支持async/await但是你仍然需要一个转换器。

注意要使用async/await编译es5 ,如果promises不在环境中,则需要Priomise库,并且可以使用流动的tconfig.json:

"compilerOptions": {
    "target": "es5",
    "lib": [
        "es5",
        "es2015.promise",
        "dom"
    ]
}

纯js方法可以使用onDone回调来通知调用者函数何时真正完成。 这更好的是直接在alertFunc添加代码,因为其他答案建议,因为这将使alertFunc不再可重用:

function call() {
    myFunction('normal1', 'heading1', 'message1', function () {
        myFunction('normal2', 'heading2', 'message2', function () {
            myFunction('normal3', 'heading3', 'message3', function () {
                // DOne
            });
        });
    });
}
function myFunction(msgType, heading, message, onDone) {
    console.log(!!document.getElementById("snackbarParent"), document.getElementById('snackbarParent'));
    if (document.getElementById("snackbarParent") == null) {
        alertFunc(msgType, heading, message, onDone);
    }
    else {
        setTimeout(function () {
            var parent = document.getElementById('snackbarParent');
            parent.parentNode.removeChild(parent);
            alertFunc(msgType, heading, message, onDone);
        }, 3500);
    }
}
function alertFunc(msgType, heading, message, onDone) {
    var div = document.createElement('div');
    div.className = 'snackbarParent';
    div.id = "snackbarParent";
    div.innerHTML = '<div id="snackbar"><b style="color:' + msgType + '"> ' + heading + ' </b>' + message + '</div>';
    document.documentElement.appendChild(div);
    // Get the snackbar DIV
    var x = document.getElementById("snackbar");
    // Add the "show" class to DIV
    x.className = "show";
    setTimeout(function () {
        x.className = x.className.replace("show", "");
        alert("Should display " + heading + " " + message + " now!");
        if (onDone)
            onDone();
    }, 3000);
}

 var massages = []; massages[0] = ['normal1','heading1','message1']; massages[1] = ['normal2','heading2','message2']; massages[2] = ['normal3','heading3','message3']; function settime(i){ setTimeout(fn,3000,i) } function fn(i){ var heading = massages[i][1], message = massages[i][2], msgType = massages[i][0]; let x = document.getElementById("snackbar"); x.innerHTML = '<div id="snackbar"><b style="color:' + msgType + '"> ' + heading + ' </b>' + message + '</div>'; alert("Should display "+heading+" "+message+" now!"); if(i<massages.length-1) {i++;settime(i)}; } 
 <p>Click the button to wait 3 seconds, then alert "Hello".</p> <button onclick="settime(0)">Try it</button> <div id='snackbar'></div> 

尝试这种模式

function callMe(yourParam){
//you can conditionly modify your param 
//if (somecondition)
// newParam=yourPram ... 
setTimeout(()=>callMe(newParam),1000)
}

实际上,执行它并不是一个好方法,但在这种情况下,你不能连续调用myFunction函数,因为setTimeout运行异步并且不阻塞线程。 所以,像这样修改alertFunc ;

function alertFunc(msgType,heading,message) {

    let div = document.createElement('div');
        div.className = 'snackbarParent';
        div.id = "snackbarParent";
        div.innerHTML = '<div id="snackbar"><b style="color:' + msgType + '"> ' + heading + ' </b>' + message + '</div>';

        document.documentElement.appendChild(div);
        // Get the snackbar DIV
        let x = document.getElementById("snackbar");

        // Add the "show" class to DIV
        x.className = "show";
    setTimeout(function(){
            if(msgType == "normal1")
            {
                 myFunction('normal2','heading2','message2');//Call second function after first one completed
            }
            if(msgType == "normal2")
            {
                 myFunction('normal3','heading3','message3');//Call third function after second one completed
            }
        x.className = x.className.replace("show", "");
        alert("Should display "+heading+" "+message+" now!");
    }, 3000);

}

Call函数看起来像;

function call(){
   myFunction('normal1','heading1','message1'); //Just call first function in the beginning
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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