一. 数组过滤
思路
循环数组每一项,将数组的元素和索引传入fn函数,并执行fn,将执行fn的结果作为过滤条件
解决方法
循环数组每一项,将数组的元素和索引传入fn函数,并执行fn,将执行fn的结果作为过滤条件
实现
/**
* @param {number[]} arr
* @param {Function} fn
* @return {number[]}
*/
var filter = function(arr, fn) {
const results = [];
arr.forEach((item, i) => {
if (fn(arr[i], i)) {
results.push(arr[i]);
}
});
return results;
};
二. 数组转换
思路
循环数组每一项,将数组的元素和索引传入fn函数,并执行fn,将执行fn的结果作为转换项输出到对应的数组中
解决方法
循环数组每一项,将数组的元素和索引传入fn函数,并执行fn,将执行fn的结果作为转换项输出到对应的数组中
实现
/**
* @param {number[]} arr
* @param {Function} fn
* @return {number[]}
*/
var map = function(arr, fn) {
const results = [];
arr.forEach((item, i) => {
results.push(fn(item, i));
});
return results;
};
三. Promise对象池
思路
方案1. Promise实现 方案2. es6中generator生成器 方案3. 通过Promise.allSettled + Promise.race实现 。。。 这里还有其它方案,这里只列举我想到的一些方案
解决方法
方案1:
定义一个index, count变量,用于记录当前需要执行的任务索引和已经执行完成的数量
定义一个runTask函数,用来循环执行当前要执行的任务
1.1 通过count来记录已经执行完的任务数量,将其和functions.length来比较,如果相等,就说明,所有任务都已经执行完成
1.2 通过索引来判断是否还有任务执行,有的话就通过递归runTask函数,继续执行任务
- 通过循环来执行runTask函数,这里结束条件为i < n && i < functions.length
方案2:
通过Symbol.iterator,给functions添加一个可迭代对象
定义一个execute函数,它接受两个参数,可迭代对象和n
2.1 根据传入的n来创建一个,可迭代循环的数组
2.2 通过循环来调用迭代对象的next方法,获取迭代对象的返回,将其返回的值作为数组的每一项
2.3 通过Promise.all来接收刚创建的数组的返回值
方案3: 这里不过多赘述了,直接看下面的实现吧
实现
方案1:
/**
* @param {Function[]} functions
* @param {number} n
* @return {Function}
*/
var promisePool = async function(functions, n) {
return new Promise((resolve) => {
if (functions.length === 0) {
resolve();
return;
}
// 当前任务索引 完成数量
let index = 0, count = 0;
function runTask() {
let currentTask = functions[index];
index ++;
currentTask().then(res => {
count ++;
if (count === functions.length) {
resolve();
}
if (index < functions.length) {
runTask();
}
});
}
for (let i = 0; i < functions.length && i < n; i ++) {
runTask();
}
});
};
/**
* const sleep = (t) => new Promise(res => setTimeout(res, t));
* promisePool([() => sleep(500), () => sleep(400)], 1)
* .then(console.log) // After 900ms
*/
方案2:
/**
* @param {Function[]} functions
* @param {number} n
* @return {Function}
*/
var promisePool = async function(functions, n) {
async function execute(iter, n) {
const promiseArr = Array(n).fill(0).map(async () => {
while(true) {
const response = iter.next();
if (response.done) break;
await response.value();
}
});
return Promise.all(promiseArr);
}
const iter = functions[Symbol.iterator]();
return execute(iter, n);
};
/**
* const sleep = (t) => new Promise(res => setTimeout(res, t));
* promisePool([() => sleep(500), () => sleep(400)], 1)
* .then(console.log) // After 900ms
*/
方案3:
/**
* @param {Function[]} functions
* @param {number} n
* @return {Function}
*/
var promisePool = async function(functions, n) {
const results = [];
const queue = new Set();
for (const task of functions) {
const response = task().then(res => {
results.push(res);
queue.delete(response);
});
queue.add(response);
if (queue.size >= n) {
await Promise.race(queue);
}
}
await Promise.allSettled(queue);
return results;
};
/**
* const sleep = (t) => new Promise(res => setTimeout(res, t));
* promisePool([() => sleep(500), () => sleep(400)], 1)
* .then(console.log) // After 900ms
*/