簡體   English   中英

在另一個(異步)函數完成后,在JavaScript中完成一個函數

[英]Executing a function after an another (asynchronous) function finishes in JavaScript

請給我一個vanilla JS解決方案,因為我不熟悉編碼和介紹庫會讓我更加困惑。

我在程序中有兩個函數:changeText包含異步setTimeout函數,它們在X秒時淡入淡出文本,userNameinput允許用戶輸入文本輸入,然后在瀏覽器上顯示輸入。

我遇到的問題是usernameinput與changeText函數一起執行。我的目標是讓changeText函數先執行並完成,然后讓userNameInput(文本輸入行出現)執行。

正如您在我的代碼中看到的,我已經實現了一個回調,試圖解決這個問題。 我創建了一個名為welcome的新函數,將changeText和useNameInput函數捆綁在一起,這樣當調用welcome時,它將首先執行changeText,然后完成,然后喚起回調中打包的userNameInput。 不知怎的,我相信由於changeText函數中的setTimeout函數被放置在Javascript環境之外的隊列中一段時間​​,因此JS看到堆棧中沒有任何內容並且在沒有等待的情況下繼續執行usernameInput。 請幫忙! 被卡住太久了! 提前致謝。

HTML:

<div id="h1">Hello,<br></div>
    <div id="inputDiv"></div>

CSS:

 #h1{
      opacity: 0;
      transition: 1s;
}

JS:

function fadeIn() {
  document.getElementById('h1').style.opacity = '1';
}

function fadeOut() {
  document.getElementById('h1').style.opacity = '0';
}

var dialogue = ['Hello,', 'My name is Jane.', 'I have a dog!', 'What is your name?'];

var input = document.createElement("input");
input.setAttribute("type", "text");
input.setAttribute("value", "");
input.setAttribute("placeholder", "Type your name then press Enter");
input.setAttribute("maxLength", "4");
input.setAttribute("size", "50");
var parent = document.getElementById("inputDiv");
parent.appendChild(input);
parent.style.borderStyle = 'solid';
parent.style.borderWidth = '0px 0px .5px 0px';
parent.style.margin = 'auto';


function changeText() {
  var timer = 0;
  var fadeOutTimer = 1000;
  for (let i = 0; i < dialogue.length; i++) {
    setTimeout(fadeIn, timer);
    setTimeout(fadeOut, fadeOutTimer);
    setTimeout(function () {
      document.getElementById('h1').innerHTML = dialogue[i];
    }, timer);
    timer = (timer + 3000) * 1;
    fadeOutTimer = (fadeOutTimer + 3000) * 1.1;
    console.log(timer, fadeOutTimer);
  }
}

function welcome(callback) {
  changeText();
  callback();
}
welcome(function () {
  function userNameInput() {
    function pressEnter() {
      var userName = input.value;
      if (event.keyCode == 13) {
        document.getElementById('h1').innerHTML = "Nice to meet you" +
          " " + userName + "!";
      }
    }
    input.addEventListener("keyup", pressEnter);
  }
  userNameInput();
});

如果我想總結一下,你運行的問題如下:

你有兩個函數使用setTimeout來執行一些延遲的代碼。 由於setTimeout沒有阻塞,它將“立即”注冊setTimeout的回調並繼續執行函數的其余部分。

function a() {
    setTimeout(function() {
        console.log('a');
    }, 500)
} 

function b() {
    setTimeout(function() {
        console.log('b');
    }, 250)
}

a();
b();

在這里你想要在500ms之后獲得“a”然后在另外250ms之后獲得“b”但是你在250ms之后獲得“b”而在另外250ms之后獲得“a”。

這樣做的舊方法是使用這樣的回調:

function a(callback) {
    setTimeout(function() {
        console.log('a');
        callback();
    }, 500)
} 

function b() {
    setTimeout(function() {
        console.log('b');
    }, 250)
}

a(b)

因此,a將調用b本身。

這樣做的一種現代方法是使用promises / async / await:

function a() {
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log('a');
            resolve();
        }, 500)
    });
}

function b() {
    return new Promise(function(resolve) {
        setTimeout(function() {
            console.log('b');
            resolve();
        }, 250);
    });
}

然后打電話:

a().then(b).then(function() {/* do something else */})

或者,在異步函數中:

async function main() {
    await a();
    await b();
    // do something else
}

main()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM