1.实现promise.all方法
promise.all方法接受一个Promise可迭代协议的参数, 只返回一个Promise实例, 返回的成功的结果resolve回调的结果是一个数组;等所有的promise,resolve都有结果后返回;只要任何一个promise的reject执行回调;就立即抛出错误,并且抛出是第一个reject的信息结果。
第一种方式:
Promise.prototype.all = function(arr) {
const strings = Object.Prototype.toString;
if(!arr || !arr.length || strings.call(arr) !== '[object Array]') {
throw new TypeError('promise must be an Array');
}
const resArr = [];// 保存resolve结果
for(let i = 0; i < arr.length; i++) {
const p = arr[i];
p.then(res => {
resArr[i] = res; // 按顺序保存到数组里
}).catch(e => {
return Promise.reject(e); //有失败就返回失败信息 不再往后执行
})
}
// 2.如果全部promise都成功回调 返回结果 []
return Promise.resolve(resArr);
}
第二种:
Promise.ptototype.all = function(promises) {
if(promises.constructor !== Array) {
throw new TypeError('arguments must be an Array')
}
let count = 0;
const resArr = [];
return new Promise(function(resolve, reject){
promises.forEach((p, i) => {
p.then(res => {
count++;
resArr[i] = res; // 保存到数组里
// 当promise成功的索引等于传递长度时就调用成功函数
count === promises.length && resolve(resArr);
}, e => {
reject(e); // 执行失败
})
})
})
}
2.手撕Promise.race方法
MDN文档
Promise.race方法接受可迭代对象, 例如Array
一旦迭代器中promise有的结果,就返回第一个promise的resolve或reject
迭代器为空就返回 promise 将永远等待。
Promise.prototype.race = function(promises) {
if(!promises || !promises.length) {
return new Promise(); // 返回永久等待。
}
return new Promise((resolve, reject) => {
promises.forEach((p) => {
p.then(resolve, reject); // 谁先返回就调用谁。
})
})
}
防抖和节流?
防抖函数(debounce)
短时间内多次触发同一事件,只触发最后一次,或者只执行最开始的一次,中间的不执行
非立即执行(执行最后一次)
// 非立即执行
// 接受两个参数 fn 函数体, wait 时间
function debounce(fn, wait) {
// 定时器变量
let timer = null;
return function() {
let that = this;
let args = arguments; // 保存执行传递进来的参数
if(timer) clearTimeout(timer)// 在执行中就清空
timer = setTimeout(function() {
fn.call(that, ...args); // this指向调用的函数
}, wait)
}
}
立即执行(执行开始一次)
function debounce(fn, wait) {
let timer = null;
return function() {
const args = arguments;
const that = this;
const now = !timer; // 当没有定时器的时候就执行
setTimeout(_ => timer = null, wait); // 执行到了就清空
if(now) {
fn.call(that, ...args);
}
}
}
节流函数(throttle)
在同一时间里面执行函数,再次触发不会被中断,直到执行完成后才可以执行下一次函数。
/**
* 定时器版本
*/
function throttle(fn, wait) {
let timer = null;
return function() {
const args = arguments
const that = this;
if(timer) return; // 还在执行返回
timer = setTimeout(function() {
fn.call(that, ...args);
clearTimeout(timer); // 执行完成清理定时器
},wait)
}
}
时间戳版本
function throttle(fn, wait) {
let now = 0;
return function() {
const args = arguments;
const that = this;
const _newDate = Date.now();
if(newDate - now > wait) {
fn.call(that, ...args);
now = _newDate;
}
}
}