在JavaScript中另一个(异步)函数完成之后执行一个函数

时间:2019-06-16 00:04:18

标签: javascript asynchronous callback synchronization

请给我一个普通的JS解决方案,因为我是编码和引入库的新手,只会使我感到困惑。

程序中有两个功能: changeText包含异步setTimeout函数,该函数可以在X秒钟内淡入和淡出文本,还有userNameinput,它允许用户输入文本输入,然后在浏览器中显示输入。

我遇到的问题是用户名输入正在与changeText函数一起执行。我的目标是先执行changeText函数并完成,然后在紧随其后执行userNameInput(出现文本输入行)。 / p>

您可以在我的代码中看到,我已经实现了一个回调,以解决此问题。我创建了一个名为welcome的新函数,将changeText和useNameInput函数捆绑在一起,这样,在调用welcome时,它将首先执行changeText,完成后再调用包装在回调函数中的userNameInput。我以某种方式相信,由于changeText函数中的setTimeout函数在Java脚本环境之外的队列中放置了X倍的时间,因此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();
});

1 个答案:

答案 0 :(得分:1)

如果我想总结一下,您遇到的问题是以下问题:

您有两个使用setTimeout延迟执行某些代码的函数。由于setTimeout没有阻塞,它将“立即”注册setTimeout的回调并继续执行其余功能。

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

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

a();
b();

在这里,您希望在500毫秒后获得“ a”,然后在另外250毫秒后获得“ b”,但是在250毫秒之后获得“ b”,而在另外250毫秒之后获得“ 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()