- 1. 实现一个带并发限制的异步调度器
Scheduler
- 2. 请实现一个cacheRequest方法
- 3. 说出 child 的盒子模型
- 4. 说出执行结果
- 5. 写一个通用算法将该数组结构转换为以下菜单结构
- 6. 判断数组是否可以分为和相等的三部分
- 7. 实现重复函数
# 1. 实现一个带并发限制的异步调度器 Scheduler
实现一个带并发限制的异步调度器 Scheduler
,保证同时运行的任务最多有两个。完善下面代码中的 Scheduler
类,使得以下程序能正确输出。
class Scheduler {
add(promiseCreator) { ... }
// ...
}
const timeout = (time) => new Promise(resolve => {
setTimeout(resolve, time)
})
const scheduler = new Scheduler()
const addTask = (time, order) => {
scheduler.add(() => timeout(time)).then(() => console.log(order))
}
addTask(1000, '1')
addTask(500, '2')
addTask(300, '3')
addTask(400, '4')
class Scheduler{
constructor() {
this.pendingState = []
this.doingJobs = 0
}
add = (promiseCreator) => {
return new Promise((resolve, reject) => {
// 关键是给传过来的函数加个回调属性,当resolved的时候,就能返回对应的结果了。
promiseCreator.resolve = resolve
promiseCreator.reject = reject
this.pendingState.push(promiseCreator)
this.doJob()
})
}
doJob = () => {
if (this.doingJobs < 2) {
if (this.pendingState.length) {
this.doingJobs += 1
const job = this.pendingState.shift()
job().then(res => {
job.resolve(res)
}).catch(e => {
job.reject(e)
}).finally(() => {
this.doingJobs -= 1
this.doJob()
})
}
}
}
}
# 2. 请实现一个cacheRequest方法
请实现一个cacheRequest方法,保证当使用ajax(请求相同资源时,此题中相同资源的判断是以url为判断依据),真实网络层中,实际只发出一次请求(假设已存在request方法用于封装ajax请求,调用格式为:request(url, successCallback, failCallback)
)
比如调用方代码(并行请求)如下
cacheRequest('/user', data => {
console.log('我是从A中请求的user,数据为' + data);
})
cacheRequest('/user', data => {
console.log('我是从B中请求的user,数据为' + data);
})
const pendingUrlList = {}
const ajaxRes = {}
function catchRequest(url, callback) {
if (ajaxRes[url]) {
callback(ajaxRes[url])
return
}
if (pendingUrlList[url]) {
pendingUrlList[url].push(callback)
return
} else {
pendingUrlList[url] = [callback]
}
request(url, (res) => {
pendingUrlList[url].map(cb => cb(res))
ajaxRes[url] = res
delete pendingUrlList(url)
}, () => {
delete pendingUrlList(url)
})
}
# 3. 说出 child 的盒子模型
<style>
.parent {
background: red;
width: 100px;
height: 100px;
padding: 0;
margin: 0;
}
.child {
background: green;
width: 50px;
height: 50px;
padding: 10%;
border: 10px solid black;
box-sizing: border-box;
}
</style>
<div class="parent">
<div class="child"></div>
</div>
padding百分比特点: padding的百分比是相对于父元素宽度,如果父元素有宽度,相对于父元素宽度,如果没有,找其父辈元素的宽度,均没设宽度时,相对于屏幕的宽度。
padding
是相对最近父级元素的,也就是100*10% = 10px
,而不是相对自身的width
,那么content
的width
就是50 - 10 * 2 - 10 * 2 = 10px
。
# 4. 说出执行结果
Function.prototype.a = () => alert(1);
Object.prototype.b = () => alert(2);
function A() {}
const a = new A();
a.a();
a.b();
答案: a.b()可以正常执行,a.a()报错
# 5. 写一个通用算法将该数组结构转换为以下菜单结构
let menu = [
{ "Id": 1, "ParentId": null, "Sort": 0, "Name": "菜单1" },
{ "Id": 2, "ParentId": 1, "Sort": 0, "Name": "菜单1-1"},
{ "Id": 3, "ParentId": 1, "Sort": 1, "Name": "菜单1-2"},
{ "Id": 4, "ParentId": 2, "Sort": 2, "Name": "菜单1-1-2"},
{ "Id": 5, "ParentId": 2, "Sort": 1, "Name": "菜单1-1-1"},
{ "Id": 6, "ParentId": null, "Sort": 1, "Name": "菜单2" },
{ "Id": 7, "ParentId": 6, "Sort": 0, "Name": "菜单2-1"},
{ "Id": 8, "ParentId": 6, "Sort": 1, "Name": "菜单2-2"},
{ "Id": 9, "ParentId": 8, "Sort": 2, "Name": "菜单2-2-2"},
{ "Id": 10, "ParentId": 8, "Sort": 1, "Name": "菜单2-2-1"},
{ "Id": 11, "ParentId": 10, "Sort": 0, "Name": "菜单2-2-1-1"}
]
<ul>
<li>
<a>菜单1<a>
<ul>
// 子菜单节点
</ul>
</li>
// 其他节点
</ul>
function getTotal(menu) {
return menu.reduce((acc, item) => {
if (item.ParentId) {
helper(acc, item)
} else{
acc.push(item)
}
return acc
}, [])
}
function helper(acc, item) {
if (!acc) return
for (let obj of acc) {
if (obj.Id === item.ParentId) {
obj.children = obj.children || []
obj.children.push(item)
obj.children.sort((a, b) => a.Sort - b.Sort)
}
helper(obj.children, item)
}
}
function generateMenuHtml() {
const newData = getTotal(menu)
const res = newData.map(item => getItemHtml(item)).join('')
return res
}
function getItemHtml(item) {
return `
<ul>
<li>
<a>${item.Name}</a>
${item.children ? item.children.map(it => getItemHtml(it)).join('') : ''}
</li>
</ul>
`
}
generateMenuHtml(menu)
# 6. 判断数组是否可以分为和相等的三部分
Consider an array A of n integers. Implement one function "split" to determine if array A can be split into three consecutive parts such that sum of each part is equal. If yes return true, otherwise return false;
Examples:
example 1:
• input:[0,2,1,-6,6,-7,9,1,2,0,1]
• output:true
• explanation:0 + 2 + 1 = -6 + 6 - 7 + 9 + 1 = 2 + 0 + 1
function split(arr) {
// implement
const len = arr.length
if (len < 3) return false
let sum = 0
for (let item of arr) {
sum += item
}
if (sum % 3) {
return false
}
let s = 0
let flag = 0
for (let item of arr) {
s += item
if (s == sum / 3) {
flag += 1
s = 0
}
}
if (flag && flag % 3 === 0) return true
return false
}
# 7. 实现重复函数
function repeat(times, mills, func) {
}
// example:
let log3 = repeat(3, 1000, console.log);
log3('hello', 'world');
log3('hello', 'world', '2');
// 1000ms后
// 输出hello world
// 输出hello world 2
// 又过1000ms后
// 输出hello world
// 输出hello world 2
// 又过1000ms后
// 输出hello world
// 输出hello world 2
function repeat(times, mills, func) {
return function () {
const args = [...arguments]
const _this = this
let _times = times
const timer = setInterval = (() => {
if (_times > 0) {
func.apply(_this, args)
_times -= 1
} else {
clearInterval(timer)
}
}, mills)
}
}