今天听说了一道微信的前端面试题,内容大概如下:
实现一个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。
1 2 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;
|
测试:
1 2
| var LazyMan = require('./LazyMan'); LazyMan('Hank').sleepFirst(10).eat('breadfast').sleep(5).eat('lunch').sleep(10).eat('dinner');
|
该问题也可以使用Promise来解决。
1 2 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;
|
测试:
1 2
| var LazyMan = require('./LazyMan'); LazyMan('Hank').sleepFirst(5).eat('breadfast').sleep(5).eat('lunch').sleep(5).eat('dinner').print();
|
print是用来取出最后一个promise的消息。
当然也可以用async来做。
1 2 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;
|
测试:
1 2
| var LazyMan = require('./LazyMan'); LazyMan('Hank').sleepFirst(5).eat('breadfast').sleep(5).eat('lunch').sleep(5).eat('dinner');
|
以上测试都在nodejs环境跑,欢迎拍砖~!