首页 > 解决方案 > 使用 vanilla Javascript ES6 的链延迟函数

问题描述

你如何像 jQuery 库那样实现延迟?- 我知道这个问题已经被问过很多次了,但还没有看到有人使用async/awaitES6 风格来实现它。让我知道你是否有想法

//create a jquery like library
class DOM {
    constructor(selector){
        this.elements = [];
        if(!selector){
            return;
        } else if(selector === 'document' || selector === 'window'){
            this.elements = [selector];
        } else {
            this.elements = Array.from(document.querySelectorAll(selector));
        }
    }

    on(){
        console.log('on');
        return this;
    }

    get(){
        console.log('get');
        return this;
    }


    delay(ms, callback){
        //how to implement this? how to chain result of callback onto next chain?
        console.log('delay');
        const promise = Promise.resolve();
        return promise.then(function(resolve) {
            setTimeout(function(){
                resolve(this);
            }, ms);
        });
    }
}

const $ = function(selector) {
    return new DOM(selector);
}       

$('document').on().delay(10000).get()

标签: javascript

解决方案


您可能不需要承诺或根本不需要async/await,我认为您可以创建一个拦截后续调用的代理对象。

这个想法是,当.delay(duration)被调用时,它将返回一个代理对象而不是类实例。这个代理对象会拦截一个方法调用,设置超时时间duration,然后用原来的类实例调用方法。

class J {
  constructor(selector) {
    this.$element = document.querySelector(selector)
  }
  delay(duration) {
    const proxy = new Proxy(this, {
      get: (target, prop) => {
        const f = target[prop]
        return (...args) => {
          setTimeout(() => {
            return f.apply(target, [...args])
          }, duration)

          // return the class instance again, so subsequent call & delay still works
          return this
        }
      }
    })
    return proxy
  }
  text(content) {
    this.$element.textContent = content
    return this
  }
}

const $ = selector => new J(selector)

$('#test').text('hello').delay(1000).text('world')
<div id="test"></div>


推荐阅读