在上一个完成后执行两次异步功能

时间:2018-10-07 16:28:30

标签: javascript es6-promise

我试图一次又一次执行一次async函数。但是问题在于它们正在一起执行。但是,我想要的是第二个执行必须在第一个执行完成之后开始。

  

PS,关于SO的问题很多,标题相同,例如JavaScript: execute async function one by one。但是他们都没有解决我的问题。

请检查Fiddle

$(document).ready(function() {
  function typeWriter(element, msg, speed, index = 0) {
    if (index < msg.length) {
      $(element).html($(element).html() + msg.charAt(index++));
      setTimeout(function() {
        typeWriter(element, msg, speed, index);
      }, speed);
    }
  }

  $('.intro').fadeIn(function() {
    const greet = new Promise(function(resolve, reject) {
      typeWriter('#sayHello', "Hello !!", 200);
      resolve();
    });
    greet.then(function() {
      typeWriter('#myName', "I'm learning programming", 200);
    });
  });
});
.intro {
  text-align: center;
  display: none;
  font-family: 'Amaranth', sans-serif;
}

.cursor {
  display: inline-block;
  width: 10px;
  height: inherit !important;
}

.cursor>span {
  display: inline-block;
  position: relative;
  top: 2px;
  width: 3px;
  height: 26px;
  margin: 0 0 0 0px;
  background-color: #000;
  animation: blink 1s step-end infinite;
}

@keyframes blink {
  from,
  to {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="intro">
  <h1 class="title"><span id="sayHello"></span><span class="cursor"><span></span></span>
  </h1>
  <h1 class="title"><span id="myName"></span><span class="cursor"><span></span></span>
  </h1>
</div>

在这里,我正在尝试在两个不同的print标记中插入两行文本。为此,我要致电<h1>两次,每个function typeWriter(...)一次。我正在尝试<h1>两行,上一行完成后进行一行,即在第一次调用中打印print,完成后再在第二行中打印Hello !!,但不是发生。问题是他们一起执行。

在进一步寻找解决方案时,我发现了这个问题JavaScript: execute async function one by one,并遵循@DavidHedlund给出的答案,但这对我不起作用。抱歉,如果我有任何错误。 请看一下我在@DavidHedlund答案中尝试过的小提琴。在这种情况下,仅打印I'm Learning Programming

Hello !!
$(document).ready(function() {
  function typeWriter(element, msg, speed, index = 0) {
    if (index < msg.length) {
      $(element).html($(element).html() + msg.charAt(index++));
      setTimeout(function() {
        typeWriter(element, msg, speed, index);
      }, speed);
    }
  }

  $('.intro').fadeIn(function() {

    function executeTasks() {
      var tasks = Array.prototype.concat.apply([], arguments);
      var task = tasks.shift();
      task(function() {
        if (tasks.length > 0)
          executeTasks.apply(this, tasks);
      });
    }

    function createTask(param) {
      let element = param[0];
      let msg = param[1];
      let speed = param[2];
      return function(callback) {
        setTimeout(function() {
          if (typeof callback == 'function') typeWriter(element, msg, speed);
        }, 1);
      }
    }
    var t1 = createTask(['#sayHello', "Hello !!", 200]);
    var t2 = createTask(['#myName', "I'm Anshuman Gupta", 200]);
    executeTasks(t1, t2);
  });
});
.intro {
  text-align: center;
  display: none;
  font-family: 'Amaranth', sans-serif;
}

.cursor {
  display: inline-block;
  width: 10px;
  height: inherit !important;
}

.cursor>span {
  display: inline-block;
  position: relative;
  top: 2px;
  width: 3px;
  height: 26px;
  margin: 0 0 0 0px;
  background-color: #000;
  animation: blink 1s step-end infinite;
}

@keyframes blink {
  from,
  to {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}

谢谢!

3 个答案:

答案 0 :(得分:1)

因此,这里发生的是typeWriter()方法正在使用setTimeout(),该方法适用于线程模型(即setTimeout()不会阻塞线程,而是会立即返回)。因此,typeWriter()方法立即返回,因此相应的promise得以解析。

尝试此代码

$(document).ready(function() {
    function typeWriter(element, msg, speed) {
        return new Promise (function (resolve, reject) {
            var recursive = function (element, msg, speed, index) {
                if (index < msg.length) {
                    $(element).html($(element).html() + msg.charAt(index++));
                    setTimeout(function() {
                        recursive(element, msg, speed, index);
                    }, speed)
                } else {
                    resolve();
                }
            }
            recursive(element, msg, speed, 0)
        })
        }

    $('.intro').fadeIn(function() {
        typeWriter('#sayHello', "Hello !!", 200).then(function() {
            return typeWriter('#myName', "I'm learning programming", 200);
        });
    });
})

答案 1 :(得分:1)

或者,如果您觉得更简单,则可以使用await

$(document).ready(function() {
  function typeWriter(element, msg, speed, index = 0) {
    return new Promise((resolve, reject) => {
      if (index < msg.length) {
        $(element).html($(element).html() + msg.charAt(index++));
        setTimeout(function() {
          typeWriter(element, msg, speed, index).then(resolve).catch(reject);
        }, speed);
      } else {
        resolve();
      }
    });
  }
  
  async function typeStuff() {
    console.log("Hi");
    await typeWriter('#sayHello', "Hello !!", 200);
    await typeWriter('#myName', "I'm learning programming", 200);
  }

  $('.intro').fadeIn(function() {
    typeStuff();
  });
});
.intro {
  text-align: center;
  display: none;
  font-family: 'Amaranth', sans-serif;
}

.cursor {
  display: inline-block;
  width: 10px;
  height: inherit !important;
}

.cursor>span {
  display: inline-block;
  position: relative;
  top: 2px;
  width: 3px;
  height: 26px;
  margin: 0 0 0 0px;
  background-color: #000;
  animation: blink 1s step-end infinite;
}

@keyframes blink {
  from,
  to {
    opacity: 1;
  }
  50% {
    opacity: 0;
  }
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="intro">
  <h1 class="title"><span id="sayHello"></span><span class="cursor"><span></span></span>
  </h1>
  <h1 class="title"><span id="myName"></span><span class="cursor"><span></span></span>
  </h1>
</div>

说明:在您的代码中,您在调用resolve之后立即调用了typeWriter。问题是typeWriter不会“阻塞”,这意味着它将设置超时以在将来执行代码并立即返回。您可以避免这样做typeWriter。然后,您可以使用await(更干净,但浏览器支持较少)或typeWriter(...).then(function() { /* Do more stuff */ })(它们实际上是等效的)。

答案 2 :(得分:1)

问题是您不等待递归函数完成然后调用resolve。

 const greet = new Promise(function(resolve, reject) {
  typeWriter('#sayHello', "Hello !!", 200);
  resolve();
});
greet.then(function() {
  typeWriter('#myName', "I'm learning programming", 200);
});

尝试一下:

const timeout = (speed) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve();
    }, speed);
  });
}

$(document).ready(function() {
async function typeWriter(element, msg, speed, index = 0) {
  if (index < msg.length) {
    $(element).html($(element).html() + msg.charAt(index++));
    await timeout(speed);
    await typeWriter(element, msg, speed, index);
  }
}

$('.intro').fadeIn(function() {
    const greet = new Promise(async function(resolve, reject) {
      await typeWriter('#sayHello', "Hello !!", 200);
      resolve();
    });
    greet.then(function() {
      typeWriter('#myName', "I'm learning programming", 200);
    });
  });
});