Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LazyMan 的实现 #7

Open
sunhengzhe opened this issue Aug 4, 2017 · 1 comment
Open

LazyMan 的实现 #7

sunhengzhe opened this issue Aug 4, 2017 · 1 comment

Comments

@sunhengzhe
Copy link
Member

这道题还没毕业的时候就看到过,这段时间突然又看到,联想到 promise,感觉还是很有意思

实现一个 LazyMan:

lazyMan('rick').eat('lunch').sleep(3000).eat('dinner');

输出:

Hi!This is rick!
eat lunch
// 等待 3 秒
eat dinner

另外如果先调用了 sleepFirst 方法,要首先进行 sleep

lazyMan('rick').sleepFirst(3000).eat('lunch');

输出:

// 等待 3 秒
Hi!This is rick!
eat lunch
@sunhengzhe
Copy link
Member Author

单看 lazyMan('rick').eat('lunch').sleep(3000).eat('dinner'); 的调用可以发现 lazyman 的机制与 promise 非常相似,可以想到让 lazyman 成为一个 promise:

class Lazyman extends Promise {
    eat(food) {
        return this.then(function () {
            console.log(`eat ${food}`);
        });
    }

    sleep(time) {
        return this.then(function() {
            return new Lazyman((resolve, reject) => {
                setTimeout(resolve, time);
            });
        });
    }
}

function lazyman(name) {
    console.log(`Hi, my name is ${name}`);
    return Lazyman.resolve();
}

lazyman('Maz').eat('lunch').sleep(3000).eat('dinner');

这样就借助 promise 实现了一个 lazyman,不过缺点是实际上其实每次返回的都是另一个 lazyman 。。不太符合语义。

如果加上 sleepFirst 方法,打招呼的逻辑就不能直接输出了,可以考虑单独用一个 promise,借以打乱打招呼的顺序:

class Lazyman extends Promise {
    eat(food) {
        return this.then(() => {
            if (this.intro) {
                return this.intro().then(() => {
                    this.intro = null;
                });
            }
        }).then(function () {
            console.log(`eat ${food}`);
        });
    }

    sleep(time) {
        return this.then(function() {
            return new Lazyman((resolve, reject) => {
                setTimeout(resolve, time);
            });
        });
    }

    sleepFirst(time) {
        return this.then(() => {
            return new Lazyman((resolve, reject) => {
                setTimeout(() => {
                    this.intro().then(resolve)
                }, time);
            });
        });
    }
}

function lazyman(name) {
    const man = Lazyman.resolve();
    man.intro = () => new Promise((resolve, reject) => {
        console.log(`Hi, my name is ${name}`);
        resolve();
    })
    return man;
}

lazyman('Maz').sleepFirst(1000).eat('lunch').sleep(3000).eat('dinner');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant