今天听说了一道微信的前端面试题,内容大概如下:
实现一个LazyMan,可以按照以下方式调用:
LazyMan(“Hank”)输出:
Hi! This is Hank!
LazyMan(“Hank”).sleep(10).eat(“dinner”)输出
Hi! This is Hank!
//等待10秒..
Wake up after 10
Eat dinner~
LazyMan(“Hank”).eat(“dinner”).eat(“supper”)输出
Hi This is Hank!
Eat dinner~
Eat supper~
LazyMan(“Hank”).sleepFirst(5).eat(“supper”)输出
//等待5秒
Wake up after 5
Hi This is Hank!
Eat supper
以此类推。
这题目我觉得挺有意思的,晚上下班回来就折腾了一下。
一个简单的做法就是使用队列+next。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 
 | function LazyMan(name) {var queue = [];
 var task = {
 wait: function (second) {
 return function () {
 setTimeout(function () {
 console.log('Wake up after ' + second);
 next();
 }, second * 1000);
 };
 },
 eat: function (part) {
 return function () {
 console.log('Eat ' + part + '~');
 next();
 };
 },
 hi: function () {
 console.log('Hi! This is ' + name + '!');
 next();
 }
 };
 
 queue.push(task.hi);
 
 function next() {
 var fn = queue.shift();
 fn && fn();
 }
 
 
 setTimeout(function () {
 next();
 }, 0);
 
 return {
 sleep: function (second) {
 queue.push(task.wait(second));
 return this;
 },
 sleepFirst: function (second) {
 queue.unshift(task.wait(second));
 return this;
 },
 eat: function (part) {
 queue.push(task.eat(part));
 return this;
 }
 };
 }
 
 exports.LazyMan = LazyMan;
 
 | 
测试:
| 12
 
 | var LazyMan = require('./LazyMan');LazyMan('Hank').sleepFirst(10).eat('breadfast').sleep(5).eat('lunch').sleep(10).eat('dinner');
 
 | 
该问题也可以使用Promise来解决。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 
 | function createWaitPromise(second) {return new Promise(function (resolve, reject) {
 setTimeout(function () {
 resolve('Wake up after ' + second);
 }, second * 1000);
 });
 }
 
 function LazyMan(name) {
 var p = new Promise(function (resolve, reject) {
 resolve('Hi! This is ' + name + '!');
 });
 
 return {
 sleep: function (second) {
 p = p.then(function (msg) {
 console.log(msg);
 return createWaitPromise(second);
 });
 return this;
 },
 sleepFirst: function (second) {
 var op = p;
 p = createWaitPromise(second).then(function (msg) {
 console.log(msg);
 return op;
 });
 return this;
 },
 eat: function (part) {
 var pn = new Promise(function (resolve) {
 resolve('Eat ' + part + '~');
 });
 p = p.then(function (msg) {
 console.log(msg);
 return pn;
 });
 return this;
 },
 print: function () {
 return p.then(function (msg) {
 console.log(msg);
 });
 }
 };
 }
 
 exports.LazyMan = LazyMan;
 
 | 
测试:
| 12
 
 | var LazyMan = require('./LazyMan');LazyMan('Hank').sleepFirst(5).eat('breadfast').sleep(5).eat('lunch').sleep(5).eat('dinner').print();
 
 | 
print是用来取出最后一个promise的消息。
当然也可以用async来做。
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 
 | function createWaitFunc(second) {return function (callback) {
 setTimeout(function () {
 console.log('Wake up after ' + second);
 callback(null);
 }, second * 1000);
 }
 }
 
 function LazyMan(name) {
 
 var chain = [];
 chain.push(
 function (callback) {
 console.log('Hi! This is ' + name + '!');
 callback(null);
 }
 );
 setTimeout(function () {
 var async = require('async');
 async.series(chain);
 }, 0);
 
 return {
 sleep: function (second) {
 chain.push(
 createWaitFunc(second)
 );
 return this;
 },
 sleepFirst: function (second) {
 chain.unshift(
 createWaitFunc(second)
 );
 return this;
 },
 eat: function (part) {
 chain.push(
 function (callback) {
 console.log('Eat ' + part + '~');
 callback(null);
 }
 );
 return this;
 }
 };
 }
 
 exports.LazyMan = LazyMan;
 
 | 
测试:
| 12
 
 | var LazyMan = require('./LazyMan');LazyMan('Hank').sleepFirst(5).eat('breadfast').sleep(5).eat('lunch').sleep(5).eat('dinner');
 
 | 
以上测试都在nodejs环境跑,欢迎拍砖~!