防抖节流Promise
大约 2 分钟
啥都没有的
JavaScript
手写防抖 debounce
关键在于: 一段时间不执行, 就执行
const debounce = function (fn, delay) {
let timer = null;
return function (...args) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.call(this, ...args);
}, delay);
};
};
手写节流 throttle
const throttle = function (fn, delay) {
let flag = false;
return function (...args) {
if (flag) return;
flag = true;
setTimeout(() => {
fn.call(this, ...args);
flag = false;
}, delay);
};
};
红绿灯
const light = (color, second) => {
return new Promise((resolve) => {
setTimeout(() => {
console.log(color);
}, second * 1000);
});
};
const list = [
{
color: 'red',
time: 3,
},
{
color: 'green',
time: 2,
},
{
color: 'yellew',
time: 1,
},
];
const lightsAll = (list) => {
let promise = Promise.resolve();
list.forEach((item) => {
promise = promise.then(() => {
return light(item.color, item.time);
});
});
promise.then(() => {
orderLights(list);
});
};
lightsAll(list);
手写 Promise
// 常量定义3promise的三个状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';
// executor new Promise 传入的 函数
function MyPromise(executor) {
const self = this;
self.status = PENDING;
self.state = undefined;
self.callbackQueues = []; // 保存回调的
function resolve(value) {
if (self.status !== PENDING) {
return;
}
self.status = FULFILLED;
self.state = value;
if (self.callbackQueues.length > 0) {
self.callbackQueues.forEach((item) => {
setTimeout(() => {
item.onResolved(value);
});
});
}
}
function reject(reason) {
if (self.status !== PENDING) return;
self.status = REJECTED;
self.state = reason;
if (self.callbackQueues.length > 0) {
self.callbackQueues.forEach((item) => {
setTimeout(() => {
item.onRejected(value);
});
});
}
}
// 捕获executor函数里意外错误,如果错误改变状态
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
const defaultOnResolved = (value) => value;
const defalutOnRejected = (reason) => {
throw reason;
};
/**
* then方法指定了成功的和失败的回调函数,如果指定的不是函数,会忽略该值
* 返回一个新的promise对象,该promsie的结果onResolved和onRejected决定,状态由上个Promise决定
*/
MyPromise.prototype.then = function (onResolved, onRejected) {
// 需要判断
onResolved =
typeof onResolved === 'function' ? onResolved : defaultOnResolved;
onRejected =
typeof onRejected === 'function' ? onRejected : defalutOnRejected;
const self = this;
return new MyPromise((resolve, reject) => {
const handler = function (callback) {
try {
const result = callback(self.state);
if (result instanceof MyPromise) {
result.then(
(res) => {
resolve(res);
},
(err) => {
reject(err);
},
);
} else {
resolve(result);
}
} catch (error) {
reject(err);
}
};
if (seft.status === PENDING) {
self.callbackQueues.push({
onResolved(value) {
handle(onResolved);
},
onRejected(reason) {
handle(onRejected);
},
});
} else if (seft.status === FULFILLED) {
setTimeout(() => {
handle(onResolved);
});
} else {
setTimeout(() => {
handle(onRejected);
});
}
});
};
/**
* 传入失败回调
* 返回一个新的Promise,由于已经捕获错误了,会返回一个成功的Promise
*/
MyPromise.prototype.catch = function (OnRejected) {
return this.then(undefined, OnRejected);
};
/**
* 返回一个指定结果成功的promise
*/
MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => {
if (value instanceof MyPromise) {
value.then(resolve, reject);
} else {
resolve(value);
}
});
};
/**
* 返回一个指定reason失败的promise
*/
MyPromise.reject = function (reason) {
return new MyPromise((resove, reject) => {
reject(reason);
});
};
/**
* 返回一个新Promsie
* 所有的promise成功才成功,有一个失败就失败
*/
MyPromise.all = function (promises) {
return new Promise((resolve, reject) => {
let values = [];
promises.map((item) => {
if (item instanceof MyPromise) {
item.then((res) => {
values.push(res);
}, reject);
} else {
// 为了正确的放入values,所以也让其异步
setTimeout(() => {
values.push(item);
});
}
});
// 这里用setTiemeout是因上面的then方法是异步的,让下面的代码也异步,才能拿到最终的values数组
setTimeout(() => {
if (values.length === promises.length) {
resolve(values);
}
});
});
};
/**
* 返回一个新Promsie
* 传入的数组中第一个返回的Promise成功就成功,如果不成功就失败(第一个promise不是你传入的第一个,比如请求接口,最新拿到结果的是第一个)
*/
MyPromise.race = function (promises) {
return new MyPromise((resolve, reject) => {
promises.map((item) => {
if (item instanceof Promise) {
item.then(resolve, reject);
} else {
resolve(item);
}
});
});
};