微信的一道前端面试题

今天听说了一道微信的前端面试题,内容大概如下:

实现一个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();
}

// flush later
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 async = require('async');
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环境跑,欢迎拍砖~!