怎么调用实例去实现一些person方法

问题如下:

Person("Li");
// 输出: Hi! This is Li!

Person("Dan").sleep(10).eat("dinner");
// 输出:
// Hi! This is Dan!
// 等待10秒..
// Wake up after 10
// Eat dinner~

Person("Jerry").eat("dinner").eat("supper");
// 输出:
// Hi This is Jerry!
// Eat dinner~
// Eat supper~

Person("Smith").sleepFirst(5).eat("supper");
// 输出:
// 等待5秒
// Wake up after 5
// Hi This is Smith!
// Eat supper

表示完全没有思路

阅读 4.2k
3 个回答
class PersonReal {
    constructor (name) {
        this.name = name
        this.timeoutId = null
        this.taskQueue = []
        this.taskIsRunning = false

        function task (name) {
            console.log(`Hi! This is ${name}!`)
        }
        this.taskQueue.push(task.bind(this, name))
        this._runQueue()
    }

    eat (food) {
        const task = food => {
            console.log('Eat ' + food + '~')
        }
        this.taskQueue.push(task.bind(this, food))
        this._runQueue()
        return this
    }

    sleep (time) {
        const task = new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log(`Wake up after ${time}`)
                resolve()
            }, time * 1000)
        })
        this.taskQueue.push(task)
        this._runQueue()
        return this
    }

    sleepFirst (time) {
        const task = new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log(`Wake up after ${time}`)
                resolve()
            }, time * 1000)
        })
        this.taskQueue.unshift(task)
        this._runQueue()
        return this
    }

    _runQueue () {
        if (this.taskIsRunning) return
        this.taskIsRunning = true

        const goNext = () => {
            if (this.taskQueue.length) {
                let task = this.taskQueue.shift()
                if (task.then) {
                    task.then(() => {
                        goNext()
                    })
                } else {
                    task()
                    goNext()
                }
            } else {
                this.taskIsRunning = false
            }
        }
        Promise.resolve().then(() => {
            goNext()
        })
    }
}

function Person (name) {
    return new PersonReal(name)
}

clipboard.png

新手上路,请多包涵
      class PersonGenerator {
        taskQueue = [];

        nextTask = () => {
          if (this.taskQueue.length > 0) {
            const task = this.taskQueue.shift();
            if (typeof task === "function") {
              task();
              this.nextTask();
            }
            if (typeof task === "number") {
              console.log(`Sleep ${task} seconds \n`);
              setTimeout(() => this.nextTask(), task * 1000);
            }
          }
        };

        runTaskQueue = () => {
          setTimeout(() => this.nextTask());
        };

        constructor(name) {
          this.taskQueue.push(() => this.sayHi(name));
          this.runTaskQueue();
        }

        sayHi(name) {
          console.log(`Hi! This is ${name}! \n`);
          return this;
        }

        sleep(seconds) {
          this.taskQueue.push(seconds);
          return this;
        }

        sleepFirst(seconds) {
          this.taskQueue.splice(-1, 0, seconds);
          return this;
        }

        eat(food) {
          this.taskQueue.push(() => console.log(`Eat ${food}~ \n`));
          return this;
        }
      }

      const Person = name => new PersonGenerator(name);

      Person("Keith")
        .sleepFirst(1)
        .sleep(3)
        .eat("apple");

我觉得少东西了,每一串指令最后应该有一个终结指令,表示指令输入完成,现在开始执行。比如Person("Dan").sleep(10).eat("dinner").run();,否则的话代码什么时候开始执行?立即执行的话延迟和顺序改变就不可能了。
为了满足了上述的四个测试用例,下面代码使用了一个隐式终结符,代价是有些许延迟。

function Person(name) {
    var id = 0;
    var operations = [()=>new Promise(resolve=>{console.log(`Hi! This is ${name}`);resolve();})];
    var returnObj = {
        sleep: function(period){
            id++;
            operations.push(()=>new Promise(resolve=>{
                setTimeout(()=>{
                    console.log(`Wake up after ${period}`);
                    resolve();
                }, period * 1000);
            }));
            return returnObj.exec();
        },
        eat: function(what){
            id++;
            operations.push(()=>new Promise(resolve=>{console.log(`Eat ${what}~`);resolve();}));
            return returnObj.exec();
        },
        sleepFirst: function(period){
            id++;
            operations.splice(0, 0, ()=>new Promise(resolve=>{
                setTimeout(()=>{
                    console.log(`Wake up after ${period}`);
                    resolve();
                }, period * 1000);
            }));
            return returnObj.exec();
        },
        exec: function(){
            ((prevId)=>{
                setTimeout(()=>{
                    if(prevId === id){
                        var opts = operations.slice();
                        operations = [];
                        opts.reduce((a,b)=>a.then(b), new Promise(resolve=>resolve()));
                    }
                }, 10);
            })(id);
            return returnObj;
        }
    };
    return returnObj.exec();
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏