如何将setTimeouts转换为可链接的插件?

时间:2016-08-20 18:46:49

标签: jquery

我有以下代码:

showElem('.match');

setTimeout(function() {
    showElem('.player');

    setTimeout(function() {
        showElem('.score');

    }, inSpeed);
}, inSpeed);

此代码调用以下函数:

function showElem(elem) {
    $(elem).removeClass('fast');
    $(elem).addClass('display');
}

我想用以下代码替换第一段代码:

showElem('.match').delay(inSpeed).showElem('.player').delay(inSpeed).showElem('.score');

我将如何做到这一点?

2 个答案:

答案 0 :(得分:3)

您可以使用jQuery的queue方法来链接不需要失败条件的有序异步代码。

当你开始需要处理错误时,承诺是适用的,但在这种情况下,它们会显着过度杀伤并妨碍jQuery的本机方法。

您的初始代码

showElem('.match').delay(inSpeed).showElem('.player').delay(inSpeed).showElem('.score');

在没有重大修改的情况下与jQuery完全兼容,但它可以简化为相对容易地使用jQuery的本机函数:

//pick an element that the queue will be managed on
$('body')
  .queue(showElem('.match'))
  .delay(inSpeed)
  .queue(showElem('.player'))
  .delay(inSpeed)
  .queue(showElem('.score'));

现在它以一致的方式编写,难以实际定义showElem函数。

根据其用途,它需要采用选择器参数

function showElem(selector) {

它需要为队列返回一个函数:

  return function (next) {

当排队的函数执行时,需要调用你的方法:

    $(selector)
      .removeClass('fast')
      .addClass('display');

因为它已排队,所以需要调用dequeue,这是next参数对内部函数的作用:

    next();

一起看起来像是:

function showElem(selector) {
  return function (next) {
    $(selector)
      .removeClass('fast')
      .addClass('display');
    next();
  };
}

//pick an element that the queue will be managed on
$('body')
  .queue(showElem('.match'))
  .delay(inSpeed)
  .queue(showElem('.player'))
  .delay(inSpeed)
  .queue(showElem('.score'));

答案 1 :(得分:1)

使用您建议的语法是不可能的,因为该代码必须运行同步,而try回调是异步的。

然而,您可以使用E6执行与承诺相似的操作:

setTimeout
var inSpeed = 1000;

showElem('.match')
    .then( _ => delay(inSpeed))
    .then( _ => showElem('.player'))
    .then( _ => delay(inSpeed))
    .then( _ => showElem('.score'));

function delay(inSpeed) {
    return new Promise(function (resolve) {
        setTimeout(resolve, inSpeed);
    });
}

function showElem(elem) {
    return new Promise(function (resolve) {
        $(elem).removeClass('fast');
        $(elem).addClass('display');
        resolve();
    });
}
.fast { border: 2px solid red }
.display { background: yellow }

非ES6解决方案

这使用jQuery <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class='match fast'>match</div> <div class='player fast'>player</div> <div class='score fast'>score</div>方法和Deferred

bind
var inSpeed = 1000;

showElem('.match')
    .then(delay.bind(null, inSpeed))
    .then(showElem.bind(null, '.player'))
    .then(delay.bind(null, inSpeed))
    .then(showElem.bind(null, '.score'));

function delay(inSpeed) {
    var prom = new $.Deferred();
    setTimeout(prom.resolve, inSpeed);
    return prom;
}

function showElem(elem) {
    var prom = new $.Deferred();
    $(elem).removeClass('fast');
    $(elem).addClass('display');
    prom.resolve();
    return prom;
}
.fast { border: 2px solid red }
.display { background: yellow }