【问题标题】:Executing a function after an another (asynchronous) function finishes in JavaScript在 JavaScript 中另一个(异步)函数完成后执行一个函数
【发布时间】:2019-06-16 00:04:18
【问题描述】:

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

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

我遇到的问题是 usernameinput 与 changeText 函数一起执行。我的目标是先执行 changeText 函数并完成,然后让 userNameInput(出现文本输入行)立即执行。

正如您在我的代码中看到的,我已经实现了一个回调来尝试解决这个问题。我创建了一个名为welcome 的新函数,将changeText 和useNameInput 函数捆绑在一起,这样当调用welcome 时,它​​将首先执行changeText,完成然后调用回调中打包的userNameInput。不知何故,我相信由于 changeText 函数中的 setTimeout 函数在 Javascript 环境之外的队列中放置了 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();
});

【问题讨论】:

    标签: javascript asynchronous callback synchronization


    【解决方案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()
    

    【讨论】:

    • 使用promises/async/wait而不是回调更好吗?由于语法,我更喜欢使用回调,但它有缺点吗?
    • 性能方面,它们应该是等效的。发明的承诺是为了防止所谓的“回调地狱”,回调相互封装(及其缩进问题)。 Promise 允许您使用 .then 语法将所有内容保持在同一级别。尽管如此,它们还是相当冗长,await/async 语法允许您在底层使用它们而不会产生丑陋,语法 looking 同步 await a();等待 b();等等。 async 关键字允许你在不声明的情况下隐式地解决一个 Promise。它涵盖了很多案例,是现代的做法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-09
    • 1970-01-01
    • 2015-12-06
    • 2016-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多