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

第三方做网站电子商务综合实训报告网站建设

第三方做网站,电子商务综合实训报告网站建设,网站建设特色,wordpress.org去掉Promise 主要是为解决程序异步处理而生的#xff0c;在现在的前端应用中无处不在#xff0c;已然成为前端开发中最重要的技能点之一。它不仅解决了以前回调函数地狱嵌套的痛点#xff0c;更重要的是它提供了更完整、更强大的异步解决方案。 同时 Promise 也是前端面试中必不…Promise 主要是为解决程序异步处理而生的在现在的前端应用中无处不在已然成为前端开发中最重要的技能点之一。它不仅解决了以前回调函数地狱嵌套的痛点更重要的是它提供了更完整、更强大的异步解决方案。 同时 Promise 也是前端面试中必不可少的考察点考察内容可深可浅因此熟练掌握它是每个前端开发者的必备能力。 Promise 相对于 callback 模式的优势网上的介绍文章已经多如牛毛本文我将不再重点赘述。本文我主要会在介绍 Promise 的基础使用上重点介绍其典型的场景应用以及一些重难点场景分析主要目的是提高对 Promise 的理解及对其灵活的运用能力。 Promise 含义及基本介绍 首先 Promise 也是一个类或构造函数是 JS 原生提供的和我们自定义的类一样通过对它进行实例化后来完成预期的异步任务处理。 Promise 接受异步任务并立即执行然后在任务完成后将状态标注成最终结果成功或失败。 Promise 有三种状态初始化时刚开始执行主体任务这时它的初始状态时 pending进行中 等到任务执行完成这时根据成功或失败分别对应状态 **fulfilled成功**和 rejected失败 这时的状态就固定不能被改变了即 Promise 状态是不可逆的。 基本用法 Promise 就是一个类所以使用时我们照常 new 一个实例即可。 const myPromise new Promise((resolve, reject) {// 这里是 Promise 主体执行异步任务ajax(xxx, () { resolve(成功了); // 或 reject(失败了)}) }) 上面创建好 Promise 实例后里面的主体会立即执行比如如果是发送请求则会立即把请求发出去如果是定时器则会立即启动计时。至于请求什么时候返回我们就在返回成功的地方通过 resolve() 将状态标注为成功即可同时 resolve(data) 可以附带着返回数据。 然后在 then() 里面进行回调处理。 const myPromise new Promise((resolve, reject) {// 这里是 Promise 主体执行异步任务ajax(xxx, () { resolve(成功了);}) }) myPromise.then((data) { // 处理 data 数据 }) 这里需要注意的是当初始化 Promise 实例时主体代码是同步就开始执行了的只有 then() 里面的回调处理才是异步的因为它需要等待主体任务执行结束。技能考察时常常会通过分析执行顺序考察此处。 如下面的代码将输出 1、3、2。 const myPromise new Promise((resolve, reject) {// 这里是 Promise 主体执行异步任务console.log(1);ajax(xxx, () { resolve(成功了);}) }).then(() {console.log(2); }) console.log(3);// 最终输出 1、3、2 如果我们在调用 then() 之前Promise 主体里的异步任务已经执行完了即 Promise 的状态已经标注为成功了。那么我们调用 then 的时候并不会错过还是会执行。但需要记着即使主体的异步任务早就执行完了then() 里面的回调永远是放到微任务里面异步执行的而不是立马执行。 比如我们在主体里面仅执行一块同步代码从而不需要等待下面代码 then() 将依然最后输出。因此我们也常常利用这种方式构建微任务相对应的利用 setTimeout 构建宏任务 const myPromise new Promise((resolve, reject) {// 主体只有同步代码则 Promise 状态会立马标注为成功console.log(1);resolve(); }).then(() {console.log(2); }) console.log(3); // 最终输出为 1、3、2 Promise 异常处理 方式一通过 then() 的第 2 个参数 const myPromise new Promise(...); myPromise.then(successCallback, errorCallback); 这种方式能捕获到 promise 主体里面的异常并执行 errorCallback。但是如果 Promise 主体里面没有异常然后进入到 successCallback 里面发生了异常此时将不会进入到 errorCallback。因此我们经常使用下面的方式二来处理异常。 方式二通过 catch() 常用方案 const myPromise new Promise(...); myPromise.then(successCallback).catch(errorCallback); 这样不管是 Promise 主体还是 successCallback 里面的出了异常都会进入到 errorCallback。这里需要注意按这种链式写法才正确如果按下面的写法将会和方式一类似不能按预期捕获具体原因在后面的链式调用里面说明。 const myPromise new Promise(...); myPromise.then(successCallback); myPromise.catch(errorCallback); 方式三try…catch try catch 是传统的异常捕获方式这里只能捕获同步代码的异常并不能捕获异步异常因此无法对 Promise 进行完整的异常捕获。 链式调用 熟悉 JQuery 的同学应该很了解链式调用就是在调用了对象的一个方法后此方法又返回了这个对象从而可以继续在后面调用对象的方法。Promise 的链式调用每次调用后会返回一个新的 Promise 实例对象从而可以继续 then()或者其他 API 调用如上面的方式二异常处理中的 catch 就属于链式调用。 const myPromise new Promise((resolve) {resolve(1) }).then((data) {return data 1; })).then((data) {console.log(data) }; // 输出 2 这里需要注意的是每次 then() 或者 catch() 后返回的是一个新的 Promise和上一次的 Promise 实例对象已经不是同一个引用了。而这个新的 Promise 实例对象包含了上一次 then 里面的结果这也是为什么链式调用的 catch 才能捕获到上一次 then 里面的异常的原因。 下面的代码非链式调用每次 then 都是针对最初的 Promise 实例最后输出为 1。 const myPromise new Promise((resolve) {resolve(1) }) myPromise.then((data) {return data 1; }) romise.then((data) {console.log(data); }) // 输出 1 常用 API 我再对一些常用 API 进行一下简单说明和介绍Promise API 和大部分类一样分为实例 API 或原型方法即 new 出来的对象上的方法和静态 API 或类方法即直接通过类名调用不需要 new。注意实例 API 都是可以通过链式调用的。 实例 API原型方法 then() Promise 主体任务和在此之前的链式调用里的回调任务都成功的时候即前面通过 resolve 标注状态后进入本次 then() 回调。 catch() Promise 主体任务和在此之前的链式调用里的出现了异常并且在此之前未被捕获的时候即前面通过 reject 标注状态或者出现 JS 原生报错没处理的时候进入本次 catch()回调。 finally() 无论前面出现成功还是失败最终都会执行这个方法如果添加过。比如某个任务无论成功还是失败我们都希望能告诉用户任务已经执行结束了就可以使用 finally()。 静态 API类方法 Promise.resolve() 返回一个成功状态的 Promise 实例一般常用于构建微任务比如有个耗时操作我们不希望阻塞主程序就把它放到微任务去如下输出 1、3、2即 console.log(2) 将放到最后微任务去执行 console.log(1); Promise.resolve().then(() {console.log(2); // 作为微任务输出 2 }) console.log(3); Promise.reject() 这个与 Promise.resolve 使用类似返回一个失败状态的 Promise 实例。 Promise.all() 此方法接收一个数组为参数准确说是可迭代参数数组里面每一项都是一个单独的 Promise 实例此方法返回一个 Promise 对象。这个返回的对象含义是数组中所有 Promise 都返回了可失败可成功返回 Promise 对象就算完成了。适用于需要并发执行任务时比如同时发送多个请求。 const p1 new Promise(...); const p2 new Promise(...); const p3 new Promise(...); const pAll Promise.all([p1, p2, p3]); pAll.then((list) {// p1,p2,p3 都成功了即都 resolve 了会进入这里// list 按顺序为 p1,p2,p3 的 resolve 携带的返回值 }).catch(() {// p1,p2,p3 有至少一个失败其他成功就会进入这里 }) 注意 Promise.all 是所有传入的值都返回状态了才会最终进入 then 或 catch 回调。 Promise 的参数也可以如下常量它会转换成立即完成的 Promise 对象 Promise.all([1, 2, 3]); // 等同于 const p1 new Promise(resolve resolve(1)); const p2 new Promise(resolve resolve(2)); const p3 new Promise(resolve resolve(3)); Promise.all([p1, p2, p3]); Promise.race() 与 Promise.all() 类似不过区别是 Promise.race 只要传入的 Promise 对象有一个状态变化了就会立即结束而不会等待其他 Promise 对象返回。所以一般用于竞速的场景。 接下来来看看 Promise 具体的使用场景。 Promise 最佳实践介绍 Promise 的 API 不多使用也不复杂简单场景一看就明白不过对于一些复杂的代码模块不够熟悉的同学就会感觉比较绕。比如这些实际应用中的经验。 异步 Promise 化的两个关键 实际应用中我们尽量将所有异步操作进行 Promise 的封装方便其他地方调用。放弃以前的 callback 写法比如我们封装了一个类 classA里面需要有一些准备工作才能被外界使用以前我们可能会提供 ready(callback) 方法那么现在就可以这样 ready().then()。 另外一般开发中尽量将 new Promise 的操作封装在内部而不是在业务层去实例化。 如下面代码 // 封装 function getData(){const promise new Promise((resolve,reject){ajax(xxx, (d) {resolve(d);})});return promise }// 使用 getData().then((data){console.log(data) }) 其实处理和封装异步任务关键就是两件事 **定义异步任务的执行内容。**如发一个请求、设一个定时器、读取一个文件等**指出异步任务结束的时机。**如请求返回时机、定时器结束的时机、文件读取完成的时机其实就是触发回调的时机。 当通过 new Promise 初始化实例的时候就定义了异步任务的执行内容即 Promise 主体。然后 Promise 给我们两个函数 resolve 和 reject 来让我们明确指出任务结束的时机也就是告诉 Promise 执行的内容和结束的时机就行了不用像 callback 那样需要把处理过程也嵌套写在里面而是在原来 callback 的地方调用一下 resolve成功或 reject失败来标识任务结束了。 在实际开发中不管业务模块或者老代码多么复杂只需要抓住上述两点去进行改造就能正确地将所有异步代码进行 Promise 化。 所有异步甚至同步逻辑都可以 Promise 化只要抓住 任务内容和 任务结束时机这两点就可很清晰的来完成封装。 如何避免冗余封装 现在很多类库已经支持返回 Promise 实例了尽量避免在外面重复包装所以在使用时仔细看官方说明有的库既支持 callback 形式也支持 Promise 形式。 下面代码为冗余封装 function getData() {return new Promise((resolve) {axios.get(url).then((data) {resolve(data)})}) } 另一个案例就是有时我们会需要构建微任务或者将同步执行的结果数据以 Promise 的形式返回给业务会容易写成下面的冗余写法 function getData() {return new Promise((resolve) {const a 1;const b 2;const c a b;resolve(c);}) } 优化写法应该如下即用 Promise.resolve 快速构建一个 Promise 对象 function getData() {const a 1;const b 2;const c a b;return Promise.resolve(c); } 异常处理 前面 API 的介绍中已经有说明尽量通过 catch() 去捕获 Promise 异常需要说明的是一旦被 catch 捕获过的异常将不会再往外部传递除非在 catch 中又触发了新的异常。 如下面代码第一个异常被捕获后就返回了一个新的 Promise这个 Promise 对象没有异常将会进入后面的 then() 逻辑 const p new Promise((resolve, reject) {reject(异常啦); // 或者通过 throw new Error() 跑出异常 }).catch((err) {console.log(捕获异常啦); // 进入 }).catch(() {console.log(还有异常吗); // 不进入 }).then(() {console.log(成功); // 进入 }) 如果 catch 里面在处理异常时又发生了新的异常将会继续往外冒这个时候我们不可能无止尽的在后面添加 catch 来捕获所以 Promise 有一个小的缺点就是最后一个 catch 的异常没办法捕获当然实际出现异常的可能性很低基本不造成什么影响。 使用 async await 实际使用中我们一般通过 async await 来配合 Promise 使用这样可以让代码可读性更强彻底没有回调的痕迹了。 async function getData() {const data await axios.get(url);return data; } // 等效于 function getData() {return axios.get(url).then((data) {return data}); } 对 async await 很多人都会用但要注意几个非常重要的点。 await 同一行后面的内容对应 Promise 主体内容即同步执行的await 下一行的内容对应 then()里面的内容是异步执行的await 同一行后面应该跟着一个 Promise 对象如果不是需要转换如果是常量会自动转换async 函数的返回值还是一个 Promise 对象 比如下面写法就是不正确的 async function getData() {// await 不认识后面的 setTimeout不知道何时返回const data await setTimeout(() {return;}, 3000)console.log(3 秒到了) } 正确写法是 async function getData() {const data await new Promise((resolve) {setTimeout(() {resolve();}, 3000)})console.log(3 秒到了) } Promise 高级应用 提前预加载应用 有这样一个场景页面的数据量较大通过缓存类将数据缓存在了本地下一次可以直接使用缓存在一定数据规模时本地的缓存初始化和读取策略也会比较耗时。这个时候我们可以继续等待缓存类初始完成并读取本地数据也可以不等待缓存类而是直接提前去后台请求数据。两种方法最终谁先返回的时间不确定。那么为了让我们的数据第一时间准备好让用户尽可能早地看到页面我们可以通过 Promise 来做加载优化。 策略是页面加载后立马调用 Promise 封装的后台请求去后台请求数据。同时初始化缓存类并调用 Promise 封装的本地读取数据。最后在显示数据的时候看谁先返回用谁的。 中断场景应用 实际应用中还有这样一种场景我们正在发送多个请求用于请求数据等待完成后将数据插入到不同的 dom 元素中而如果在中途 dom 元素被销毁了比如 react 在 useEffect 中请求的数据时组件销毁这时就可能会报错。因此我们需要提前中断正在请求的 Promise不让其进入到 then 中执行回调。 useEffect(() {let dataPromise new Promise(...);let data await dataPromise();// TODO 接下来处理 data此时本组件可能已经销毁了dom 也不存在了所以需要在下面对 Promise 进行中断return (() {// TODO 组件销毁时对 dataPromise 进行中断或取消})}); 我们可以对生成的 Promise 对象进行再一次包装返回一个新的 Promise 对象而新的对象上被我们增加了 cancel 方法用于取消。这里的原理就是在 cancel 方法里面去阻止 Promise 对象执行 then()方法。 下面构造了一个 cancelPromise 用于和原始 Promise 竞速最终返回合并后的 Promise外层如果调用了 cancel 方法cancelPromise 将提前结束整个 Promise 结束。 function getPromiseWithCancel(originPromise) {let cancel (v) {};let isCancel false;const cancelPromise new Promise(function (resolve, reject) {cancel e {isCancel true;reject(e);};});const groupPromise Promise.race([originPromise, cancelPromise]).catch(e {if (isCancel) {// 主动取消时不触发外层的 catchreturn new Promise(() {});} else {return Promise.reject(e);}});return Object.assign(groupPromise, { cancel }); }// 使用如下 const originPromise axios.get(url); const promiseWithCancel getPromiseWithCancel(originPromise); promiseWithCancel.then((data) {console.log(渲染数据, data); }); promiseWithCancel.cancel(); // 取消 Promise将不会再进入 then() 渲染数据 Promise 深入理解之控制反转 熟悉了 Promise 的基本运用后我们再来深入点理解。Promise 和 callback 还有个本质区别就是控制权反转。 callback 模式下回调函数是由业务层传递给封装层的封装层在任务结束时执行了回调函数。 而 Promise 模式下业务层并没有把回调函数直接传递给封装层( Promise 对象内部)封装层在任务结束时也不知道要做什么回调只是通过 resolve 或 reject 来通知到 业务层从而由业务层自己在 then() 或 reject() 里面去控制自己的回调执行。 这里可能理解起来有点绕换种等效的简单理解我们知道函数一般是分定义 调用步骤的先定义后调用。谁调用了函数就表示谁在控制这个函数的执行。 那么我们来看 callback 模式下业务层将回调函数的定义传给了封装层封装层在内部完成了回调函数的调用执行业务层并没有调用回调函数甚至业务层都看不到其调用代码所以回调函数的执行控制权在封装层。 而 Promise 模式下回调函数的调用执行是在 then() 里面完成的是由业务层发起的业务层不仅能看到回调函数的调用代码也能修改因此回调函数的控制权在业务层。 手动实现 Promise 类的思路 现在我们已经熟悉了 Promise 的详细使用方式假设让你回到 Promise 类出现之前那时的 ES6 还没出现你为了淘汰 callback 的回调写法准备自己写一个 Promise 类你会怎么做 其实这就是常见面试手写 Promise 题目。我们只要抓住 Promise 的一些特点和关键点就能比较顺利实现。 首先 Promise 是一个类构造函数接收参数是一个函数而这个函数的参数是 resolve 和 reject 两个内部函数也就是我们需要构建 resolve 和 reject 传给它同时让它立即执行。另外咱这个类是有三种状态及 then 和 catch 等方法。根据这些就能快速先把类框架创建好。 class MyPromise () {constructor (fun) {this.status pending; // pending、fulfilled、rejectedfun(this.resolve, this.reject); // 立即执行主体函数参数函数可能需要 bind(this)}resolve() {} // 定义 resolve内容待定reject() {} // 定义 reject内容待定then() {}catch() {} } 有了雏形之后再根据对 Promise 的理解逐步完善即可如 resolve 和 reject 里面我们肯定是要去修改 status 状态的 而 then() 里面我们需要接收并保存传进来的回调等等。 完整案例可在网上搜索重点是理解它的实现思路。 总结 今天我们对 Promise 进行了基本 API 介绍然后重点对其实际应用进行了介绍和解析。相信通过本文的学习可以提升你对 Promise 的理解和运用能力。 同时文中的一些实际场景举例是非常典型的应用场景比如 async await 和手写 Promise 是很容易被考察的点。并且考察方式变化很多万变不离其宗抓住文中重点内容做到举一反三不是问题。 最后可以看一个有点难度的 Promise 执行顺序分析题目 function promise2() {return new Promise((resolve) {console.log(promise2 start);resolve();}) } function promise3() {return new Promise((resolve) {console.log(promise3 start);resolve();}) } function promise4() {return new Promise((resolve) {console.log(promise4 start);resolve();}).then(() {console.log(promise4 end);}) } async function asyncFun() {console.log(async1 start);await promise2();console.log(async1 inner);await promise3();console.log(async1 end); } setTimeout(() {console.log(setTimeout start);promise1();console.log(setTimeout end); }, 0); asyncFun(); promise4(); console.log(script end); 最后 最近找到一个VUE的文档它将VUE的各个知识点进行了总结整理成了《Vue 开发必须知道的36个技巧》。内容比较详实对各个知识点的讲解也十分到位。 有需要的小伙伴可以点击下方卡片领取无偿分享
http://www.dnsts.com.cn/news/170576.html

相关文章:

  • 做配资网站多少钱开发app需要哪些审批
  • 简约个人博客html代码德州做网站优化
  • 爱奇艺做视频网站的湘潭平台公司
  • 网站推广必做维影企业网站管理系统
  • 网站cms管理后台电话号码电子商务网站建设核心是
  • 兰州网站建设兼职女性广告
  • 网站建设技术入股合同上海文化传媒公司排名
  • 网站建站在线制作手机制作价格表的软件
  • 网站怎么样被百度收录365建站网
  • 山东专业网站建设公司随州网络优化网站建设公司
  • 嘉兴型网站系统总部文章管理系统网站模板
  • 做网站就用建站之星工业产品设计的基本特征
  • 最低价网站建设台州网站的优化
  • 合肥建设网网站网络会议网站
  • 厦门网站seo东莞网站建设招聘
  • 怎么做淘宝客采集网站自动seo系统
  • 兰州有制作网站深圳开发小程序公司
  • 替别人做网站管理员房产经纪人获客神器
  • 网站开发主管岗位职责说明书广告公司简介模板免费
  • 青岛网站设计定制移动应用开发心得体会
  • 重庆推广网站排名价格网站建立的流程
  • 西部网站管理助手基础网站怎么做
  • 服务类的网站怎么做网站开发工程师招聘信息
  • 在线商标免费设计长春seo
  • 做书封面的模板下载网站西城改版网站
  • 郑州网站优化排名推广asp网站后台验证码错误
  • 要屏蔽一个网站要怎么做网站开发中需要解决的技术问题
  • 太原0元网站建设如何做网站安全扫描
  • 同一产品做多个网站女子拿快递被感染新冠
  • 做流量网站百家号查询排名数据查询