成都网站维护公司青岛硅谷网站建设公司

当前位置: 首页 > news >正文

成都网站维护公司,青岛硅谷网站建设公司,网站建设的质量区别,vi 设计预备知识 回调函数#xff1a;当一个函数作为参数传入另一个函数中#xff0c;并且它不会立刻执行#xff0c;当满足一定条件之后#xff0c;才会执行#xff0c;这种函数称为回调函数。比如#xff1a;定时器。异步任务#xff1a;与之对应的概念是同步任务#xff0…预备知识 回调函数当一个函数作为参数传入另一个函数中并且它不会立刻执行当满足一定条件之后才会执行这种函数称为回调函数。比如定时器。异步任务与之对应的概念是同步任务同步任务是在主线程上排队执行当前面的任务执行完成才会执行下一个任务。异步任务不进入主线程而是进入异步队列前一个任务是否执行完成不影响下一个任务的指向。简单理解就是同步要按代码顺序执行异步不按照代码顺序执行异步的执行效率更高。 为什么出现Promise 存在异步任务的代码不能保证代码按照顺序执行但在特定的需要下就是需要在异步中实现顺序执行这时常使用回调函数去实现比如下面的代码 setTimeout((){console.log(找实习);setTimeout((){console.log(面试通过);setTimeout((){console.log(拿offer);setTimeout((){console.log(上班);},2000)},1000)},1000)},2000) 执行结果 虽然上面的代码能实现我们想要的结果但一些情形下需要嵌套更多回调函数时多层嵌套让代码可读性非常差后期的维护或者异常处理等都变得特别繁琐让缩进格式也变得非常麻烦。 回调函数A中嵌套回调函数B回调函数B中嵌套回调函数C…….这种回调函数多层嵌套的情况被称为回调地狱。回调地狱就是为了实现在异步任务中代码也能顺序执行而出现的一种操作。 为解决回调地狱带来的问题ES6新增了Promise类让我们能更优雅的书写复杂的异步任务。 Promise 先用一段代码认识一下Promise new Promise((resolve,reject){setTimeout((){resolve(3秒后执行)},3000) }).then(res{console.log(res);}) 是一个类需要使用new Promise来创建实例对象。promise有三种状态pending(待定)fulfilled(已兑现)rejected(已拒绝)。fulfilled和rejected也可以称为已敲定。promise初始状态是pendingpromise的状态转换有两条路一条pending-fulfilled一条pending-rejected。状态一旦改变就不能再发生变化。调用resolve()方法pending状态会变成fulfilled状态并且触发then()中第一个回调方法调用reject()方法pending状态会变成rejected状态并且触发then()中第二个回调方法。promise有三个实例方法then、catch、finally。其中catch和finally实际都是在调用then方法只是它们往then中传递的参数不一样。 catch thenundefinedreject的回调方法 finally thenA回调,A回调 promise的三个实例方法和六个静态方法都是返回一个新的promise。六个静态方法为resolve、reject、race、all、allSettled、any。其中race、all、allSettled、any将一个 Promise 可迭代对象作为输入也可以简单理解成传递数组作为参数。 promise的实例方法 下面会对三个实例方法进行重写对于相同的代码进行了提取 // 将方法放到任务队列中的方法function runAsynctask(callback) {if (typeof queueMicrotask function) {queueMicrotask(callback);} else if (typeof MutationObserver function) {// 创建观察器const obs new MutationObserver(callback);// 创建元素添加监听const divNode document.createElement(div);// 参数1 观察的dom节点// 参数2 观察的选项childList 观察子节点改变obs.observe(divNode, { childList: true });// 修改元素内容divNode.innerText 999999;} else {setTimeout(callback, 0);}}// 对then不同的返回值进行不同操作function judgmentFn(x, p, resolve, reject) {if (x p) {throw new TypeError(Chaining cycle detected for promise #Promise);}if (x instanceof QPromise) {x.then((res) resolve(res),(err) reject(err));} else {resolve(x);}} then方法 ​then() 方法最多接受两个参数用于 Promise 兑现和拒绝情况的回调函数。它返回一个 Promise 对象。 手写then方法 then(onFulfilled, onRejected) {// 参数判断onFulfilled typeof onFulfilled function ? onFulfilled : (x) x;onRejected typeof onRejected function ? onRejected : (x) {throw x;};const p new QPromise((resolve, reject) {// 执行方法if (this.state FULFILLED) {runAsynctask(() {try {const x onFulfilled(this.result);judgmentFn(x, p, resolve, reject);} catch (error) {reject(error);}});} else if (this.state REJECTED) {runAsynctask(() {try {const x onRejected(this.result);judgmentFn(x, p, resolve, reject);} catch (error) {reject(error);}});} else if (this.state PENDING) {// 保存回调函数this.#handlers.push({onFulfilled: () {runAsynctask(() {try {const x onFulfilled(this.result);judgmentFn(x, p, resolve, reject);} catch (error) {reject(error);}});},onRejected: () {runAsynctask(() {try {const x onRejected(this.result);judgmentFn(x, p, resolve, reject);} catch (error) {reject(error);}});},});}});return p;} catch方法 catch() 在 promise 被拒绝时调用catch里的函数返回一个 Promise 对象。此方法是 Promise.prototype.then(undefined, onRejected) 的一种简写形式。 catch(onRejected) {// 内部调用then方法return this.then(undefined, onRejected); } finally方法 finally() 用于注册一个在 promise 敲定兑现或拒绝时调用的函数无论是兑现还是拒绝都是调用同一个函数。 finally(onFinally) {return this.then(onFinally, onFinally);} promise的静态方法 resolve方法 Promise.resolve() 将给定的值转换为一个 Promise。如果这个值本身就是promise则直接返回这个值就算这个promise的状态是已拒绝的其它值就封装成promise返回的 Promise 将会以该值兑现。 static resolve(value) {// 如果是promise 直接返回if (value instanceof QPromise) {return value;}// 其他值就直接封装成promise返回return new QPromise((res) {res(value);}); } reject方法 reject()返回一个已拒绝的 Promise 对象拒绝原因 是给定的参数。 static reject(value) {// 不管是什么值包括 Promise 对象都重新封装成promise返回return new QPromise((undefined, reject) {reject(value);}); } race方法 race()等待第一个敲定返回一个 Promise这个返回的 promise 会随着第一个 promise 的敲定而敲定。 static race(promises) {// 返回promisereturn new QPromise((resolve, reject) {// 判断是否为数组if (!Array.isArray(promises)) {return reject(new TypeError(Argument is not iterable));}// 等待第一个敲定(promise状态的敲定)promises.forEach((p) {// 对数组中的每一项使用resolve可以保证每一项都是promise所以每一项都可以使用thenQPromise.resolve(p).then((res) {resolve(res);},(err) {reject(err);});});}); }allSettled方法 allSettled()等待全部敲定当数组中的每一个都已敲定时返回的 Promise 将被兑现并带有描述每个 Promise 结果的对象数组。 static allSettled(promises) {// 返回promisereturn new QPromise((resolve, reject) {// 判断是否为数组if (!Array.isArray(promises)) {return reject(new TypeError(Argument is not iterable));}// 空数组直接兑现promises.length 0 resolve(promises);// 等待全部敲定// 记录结果const results [];// 记录兑现次数let count 0;promises.forEach((p, index) {// 对数组中的每一项使用resolve可以保证每一项都是promise所以每一项都可以使用thenQPromise.resolve(p).then((res) {// 用索引来添加元素保证结果顺序和promise数组的顺序一致results[index] { status: FULFILLED, value: res };// 判断全部兑现count;// 通过兑现的次数进行判断保证获取到所有的结果count promises.length resolve(results);},(err) {results[index] { status: REJECTED, reason: err };count;count promises.length resolve(results);});});});}all方法 all()两种情况 当所有输入的 Promise 都被兑现时返回的 Promise 也将被兑现即使传入的是空数组并返回一个包含所有兑现值的数组。如果输入的任何 Promise 被拒绝则返回的 Promise 将被拒绝并带有第一个被拒绝的原因。 static all(promises) {// 返回promisereturn new QPromise((resolve, reject) {// 判断是否为数组if (!Array.isArray(promises)) {return reject(new TypeError(Argument is not iterable));}// 空数组直接兑现promises.length 0 resolve(promises);// 处理全部兑现// 记录结果const results [];// 记录兑现次数let count 0;promises.forEach((p, index) {// 对数组中的每一项使用resolve可以保证每一项都是promise所以每一项都可以使用thenQPromise.resolve(p).then((res) {// 用索引来添加元素保证结果顺序和promise数组的顺序一致results[index] res;// 判断全部兑现count;// 通过兑现的次数进行判断保证获取到所有的结果count promises.length resolve(results);},(err) {// 处理第一个拒绝reject(err);});});});} any方法 any()两种情况 当输入的任何一个 Promise 兑现时这个返回的 Promise 将会兑现并返回第一个兑现的值。当所有输入 Promise 都被拒绝包括空数组时它会以一个包含拒绝原因数组的AggregateError 拒绝。 static any(promises) {// 返回promisereturn new QPromise((resolve, reject) {// 判断是否为数组if (!Array.isArray(promises)) {return reject(new TypeError(Argument is not iterable));}// 空数组直接兑现promises.length 0 reject(new AggregateError(promises,All promises were rejected))// 等待结果const errors[]let count0promises.forEach((p,index){QPromise.resolve(p).then(res{// 第一个兑现resolve(res)},err{// 全部拒绝errors[index]errcountcountpromises.length reject(new AggregateError(errors,All promises were rejected))})})});} 手写Promise 手写promise的完整代码 // 三个状态const PENDING pending;const FULFILLED fulfilled;const REJECTED rejected;// 定义QPromise类class QPromise {// 初始状态state PENDING;// 初始原因result undefined;// 定义实例属性#handlers [];// 构造函数constructor(fn) {const resolve (result) {// 状态不可逆if (this.state PENDING) {// 修改状态this.state FULFILLED;this.result result;// 调用成功回调this.#handlers.forEach(({ onFulfilled }) {onFulfilled(this.result);});}};const reject (result) {// 状态不可逆if (this.state PENDING) {// 修改状态this.state REJECTED;this.result result;// 调用失败回调this.#handlers.forEach(({ onRejected }) {onRejected(this.result);});}};try {// 执行fn(resolve, reject);} catch (error) {reject(error);}}// then :将方法放到微任务队列中then(onFulfilled, onRejected) {// 参数判断onFulfilled typeof onFulfilled function ? onFulfilled : (x) x;onRejected typeof onRejected function? onRejected: (x) {throw x;};const p new QPromise((resolve, reject) {// 执行方法if (this.state FULFILLED) {runAsynctask(() {try {const x onFulfilled(this.result);judgmentFn(x, p, resolve, reject);} catch (error) {reject(error);}});} else if (this.state REJECTED) {runAsynctask(() {try {const x onRejected(this.result);judgmentFn(x, p, resolve, reject);} catch (error) {reject(error);}});} else if (this.state PENDING) {// 保存回调函数this.#handlers.push({onFulfilled: () {runAsynctask(() {try {const x onFulfilled(this.result);judgmentFn(x, p, resolve, reject);} catch (error) {reject(error);}});},onRejected: () {runAsynctask(() {try {const x onRejected(this.result);judgmentFn(x, p, resolve, reject);} catch (error) {reject(error);}});},});}});return p;}// 实例方法catch(onRejected) {// 内部调用then方法return this.then(undefined, onRejected);}// 实例方法finally(onFinally) {return this.then(onFinally, onFinally);}// 静态方法static resolve(value) {// 如果是promise 直接返回if (value instanceof QPromise) {return value;}// 其他值就直接封装成promise返回return new QPromise((res) {res(value);});}static reject(value) {// 不管是什么值包括 Promise 对象都重新封装成promise返回return new QPromise((undefined, reject) {reject(value);});}// 等待第一个敲定static race(promises) {// 返回promisereturn new QPromise((resolve, reject) {// 判断是否为数组if (!Array.isArray(promises)) {return reject(new TypeError(Argument is not iterable));}// 等待第一个敲定(promise状态的敲定)promises.forEach((p) {QPromise.resolve(p).then((res) {resolve(res);},(err) {reject(err);});});});}// 全部状态为成功则返回一个数组// 若有一个失败则处理失败static all(promises) {// 返回promisereturn new QPromise((resolve, reject) {// 判断是否为数组if (!Array.isArray(promises)) {return reject(new TypeError(Argument is not iterable));}// 空数组直接兑现promises.length 0 resolve(promises);// 处理全部兑现// 记录结果const results [];// 记录兑现次数let count 0;promises.forEach((p, index) {QPromise.resolve(p).then((res) {// 用索引来添加元素保证结果顺序和promise数组的顺序一致results[index] res;// 判断全部兑现count;// 通过兑现的次数进行判断保证获取到所有的结果count promises.length resolve(results);},(err) {// 处理第一个拒绝reject(err);});});});}// 等待全部状态敲定不管是失败还是成功状态都放在一个数组中返回static allSettled(promises) {// 返回promisereturn new QPromise((resolve, reject) {// 判断是否为数组if (!Array.isArray(promises)) {return reject(new TypeError(Argument is not iterable));}// 空数组直接兑现promises.length 0 resolve(promises);// 等待全部敲定// 记录结果const results [];// 记录兑现次数let count 0;promises.forEach((p, index) {QPromise.resolve(p).then((res) {// 用索引来添加元素保证结果顺序和promise数组的顺序一致results[index] { status: FULFILLED, value: res };// 判断全部兑现count;// 通过兑现的次数进行判断保证获取到所有的结果count promises.length resolve(results);},(err) {results[index] { status: REJECTED, reason: err };count;count promises.length resolve(results);});});});}// 返回第一个状态兑现(成功)的结果// 全部拒绝时返回拒绝的结果数组static any(promises) {// 返回promisereturn new QPromise((resolve, reject) {// 判断是否为数组if (!Array.isArray(promises)) {return reject(new TypeError(Argument is not iterable));}// 空数组直接兑现promises.length 0 reject(new AggregateError(promises,All promises were rejected))// 等待结果const errors[]let count0promises.forEach((p,index){QPromise.resolve(p).then(res{// 第一个兑现resolve(res)},err{// 全部拒绝errors[index]errcountcountpromises.length reject(new AggregateError(errors,All promises were rejected))})})});}}// 异步函数function runAsynctask(callback) {if (typeof queueMicrotask function) {queueMicrotask(callback);} else if (typeof MutationObserver function) {// 创建观察器const obs new MutationObserver(callback);// 创建元素添加监听const divNode document.createElement(div);// 参数1 观察的dom节点// 参数2 观察的选项childList 观察子节点改变obs.observe(divNode, { childList: true });// 修改元素内容divNode.innerText 999999;} else {setTimeout(callback, 0);}}// 对then不同的返回值进行不同操作function judgmentFn(x, p, resolve, reject) {if (x p) {throw new TypeError(Chaining cycle detected for promise #Promise);}if (x instanceof QPromise) {x.then((res) resolve(res),(err) reject(err));} else {resolve(x);}}如果本文对你有帮助希望能得到你的点赞或收藏或关注这是对我最好的鼓励 如你有问题或疑惑欢迎在评论区写下必将努力解答 如本文有误区希望你不吝赐教让我们共勉