js 实现可以链式调用的延时

请看题

lazyMan("Smith")
执行上面的代码输出:
Hi This is Smith!
lazyMan("Smith").sleepFirst(5).eat("lunch").sleep(3).eat('dinner');
执行上面的代码输出:
等待 5秒.
wake up after 5 seconds.
Hi!This is Smith.
Eat lunch.
等待 3秒.
wake up after 3 seconds.
Eat dinner.

思考

  • 这道比较全面也比较难,因为用到很多 js 语法,但是也比较能测出来一个人 js 水平
  • 使用链式调用,需要用到function prototype(方法的原型) 或者 ES6 class 写法,每一个函数返回 this
  • 延时需要使用 setTimeout
  • 所用任务放到一个数组里,利用数组shift()取出任务并执行
  • 一个任务里有指向下一个任务方法then()

实现

function lazyMan(name) {
    // 返回一个可以对象
    return new Lazy(name)
}

class Lazy {

    constructor(name) {
        this.tasks = []
        this.tasks.push(() => {
            console.log('Hi!This is ' + name + '.');
            this.then();
        });
        // 随后执行
        setTimeout(() => {
            this.then();
        })
    }

    eat(name) {
        // 从后进任务数组
        this.tasks.push(() => {
            console.log('Eat ' + name + '.');
            this.then();
        })
        return this;
    }

    sleep(time) {
        // 从后进任务数组
        this.tasks.push(() => {
            console.log('等待 ' + time + '秒.');
            setTimeout(() => {
                console.log('wake up after ' + time + ' seconds.');
                this.then();
            }, time * 1000)
        });
        return this;
    }

    sleepFirst(time) {
        // 从前进任务数组
        this.tasks.unshift(() => {
            console.log('等待 ' + time + '秒.');
            setTimeout(() => {
                console.log('wake up after ' + time + ' seconds.');
                this.then();
            }, time * 1000)
        });
        return this;
    }

    // 执行任务数组里的方法
    then() {
        let task = this.tasks.shift();
        task && task();
        return this;
    }

}
Leave a Reply

Your email address will not be published. Required fields are marked *