查看原文
其他

这一次,彻底弄懂 Promise

前端小贾 前端学苑 2021-07-15

关注“前端学苑” ,坚持每天进步一点点


「~彻底弄懂 Promise 原理~」

Promise的出现是为了更好地解决JavaScript中异步编程的问题,Promise可以让我们通过链式调用的方法去解决回调嵌套的问题,使我们的代码更容易理解和维护,而且Promise还增加了许多有用的特性,让我们处理异步编程得心应手。

回调方法(callback)

简单说回调方法就是将一个方法func2作为参数传入另一个方法func1中,当func1执行到某一步或者满足某种条件的时候才执行传入的参数func2。

请求1(function(请求结果1){    请求2(function(请求结果2){        处理请求结果2 }) })

某些情况下,回调嵌套很多时,代码就会非常繁琐,会给我们的编程带来很多的麻烦,这种情况俗称——回调地狱


重要说明:

优点:解决了同步的问题(只要有一个任务耗时很长,后面的任务都必须排队等着,会拖延整个程序的执行。)

缺点:回调地狱,不能用 try catch 捕获错误,不能 return。


回调地狱的根本问题:

1)缺乏顺序性:回调地狱导致的调试困难,和大脑的思维方式不符。

2)嵌套函数存在耦合性,一旦有所改动,就会牵一发而动全身,即(控制反转)。

3)嵌套函数过多的多,很难处理错误。


Promise

Promise就是为了解决callback的问题而产生的。Promise 是用来管理异步编程的,它本身不是异步的。

Promise 采用了回调函数延迟绑定技术,在执行 resolve 函数的时候,回调函数还没有绑定,那么只能推迟回调函数的执行。

let p1 = new Promise((resolve,reject)=>{ console.log(1); resolve('浪里行舟') console.log(2)})// then:设置成功或者失败后处理的方法p1.then(result=>{//p1延迟绑定回调函数 console.log('成功 '+result)},reason=>{ console.log('失败 '+reason)})console.log(3)结果:// 1// 2// 3// 成功 浪里行舟

new Promise的时候先执行executor函数,打印出 1、2,Promise在执行resolve时,触发微任务,还是继续往下执行同步任务, 执行p1.then时,存储起来两个函数(此时这两个函数还没有执行),然后打印出3,此时同步任务执行完成,最后执行刚刚那个微任务,从而执行.then中成功的方法。


1、Promise的基本用法

Promise是异步编程的一种解决方案,它有三种状态,分别是pending-进行中、resolved-已完成、rejected-已失败

new Promise( function(resolve,reject){       // 一段耗时很长的异步操作       resolve();   // 数据处理完成 reject(); // 数据处理出错 }) .then(function A() {         // 成功,下一步 }, function B() {        // 失败,做相应处理 });

.then()方法使Promise原型链上的方法,它包含两个参数方法,分别是已成功resolved的回调和已失败rejected的回调。

.catch()的作用是捕获Promise的错误,与then()的rejected回调作用几乎一致。


2、Promise链式调用

把多个Promise连接到一起来表示一系列异步骤。可以实现的关键两个Promise 固有行为特性:

1)每次你对Promise调用then,它都会创建并返回一个新的Promise,我们可以将其链接起来;

2)不管从then调用的完成回调(第一个参数)返回的值是什么,它都会被自动设置为被链接Promise(第一点中的)的完成。

new Promise(请求1)    .then(请求2(请求结果1))    .then(请求3(请求结果2))    .then(请求4(请求结果3))    .then(请求5(请求结果4)).catch(处理异常(异常信息))

3、Promise的三个缺点

1)无法取消Promise,一旦新建它就会立即执行,无法中途取消。

2)如果不设置回调函数,Promise内部抛出的错误,不会反映到外部。

3)当处于pending状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将完成。


4、Promise 的常用 API 如下:

Promise.resolve(value)  类方法,该方法返回一个以 value 值解析后的 Promise 对象

1) 如果这个值是个 thenable(即带有 then 方法),返回的 Promise 对象会“跟随”这个 thenable 的对象,采用它的最终状态(指 resolved/rejected/pending/settled)

2) 如果传入的 value 本身就是 Promise 对象,则该对象作为 Promise.resolve 方法的返回值返回。

3) 其他情况以该值为成功状态返回一个 Promise 对象。

Promise.reject   类方法,且与 resolve 唯一的不同是,返回的 promise 对象的状态为 rejected。

Promise.prototype.then 实例方法,为 Promise 注册回调函数,函数形式:fn(vlaue){},value 是上一个任务的返回结果,then 中的函数一定要 return 一个结果或者一个新的 Promise 对象,才可以让之后的then 回调接收。

Promise.prototype.catch

实例方法,捕获异常,函数形式:fn(err){}, err 是 catch 注册 之前的回调抛出的异常信息。

Promise.race

类方法,多个 Promise 任务同时执行,返回最先执行结束的 Promise 任务的结果,不管这个 Promise 结果是成功还是失败。。

Promise.all

类方法,多个 Promise 任务同时执行。

如果全部成功执行,则以数组的方式返回所有 Promise 任务的执行结果。

如果有一个 Promise 任务 rejected (数据处理出错),则只返回 rejected 任务的结果。


async、await

async、await很好的解决将异步强行转换为同步处理。async/await的实现是基于 Promise的,简单而言就是async 函数就是返回Promise对象,是generator的语法糖。是ES7中新增的异步编程方法。


async、await 是异步的终极解决方案

1)语法简洁,更像是同步代码,也更符合普通的阅读习惯;

2)改进JS中异步操作串行执行的代码组织方式,减少callback的嵌套;

3)Promise中不能自定义使用try/catch进行错误捕获,但是在Async/await中可以像处理同步代码处理错误。


规则:

1)async和await是配对使用的,await存在于async的内部。否则会报错。

2)await表示在这里等待一个promise返回,再接下来执行。

错误捕获:如果是reject状态,可以用try-catch捕捉。


重要说明:

优点:代码清晰,不用像 Promise 写一大堆 then 链,处理了回调地狱的问题

缺点:await 将异步代码改造成同步代码,如果多个异步操作没有依赖性而使用 await 会导致性能上的降低。


觉得本文对你有帮助?请分享给更多人

关注「前端学苑」加星标,提升前端技能

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存