概述:
Promise是一个构造函数,JS原生提供Promise对象。
Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及该异步操作的结果值。
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
特点:
不同于老式的传入回调,在应用 Promise 时,将会有以下特点:
1.Promise会放到微队列中,因为他是异步执行,会插入到本轮事件循环的末尾,所以会晚于同步代码执行。
2.通过 .then()形式添加的回调函数都会被调用,即便是在异步操作完成之后才被添加的函数。
3.通过多次调用 .then(),可以添加多个回调函数,它们会按照插入顺序并且独立运行。
因此,Promise 最直接的好处就是链式调用。
状态:
pending: 初始状态,既不是成功,也不是失败状态。
fulfilled: 意味着操作成功完成。
rejected: 意味着操作失败。
语法:
Promise构造函数接受一个函数作为参数,先把这个函数叫做executor。
executor是带有 resolve 和 reject 两个参数的函数 。Promise构造函数执行时立即调用executor 函数,resolve 和 reject 两个函数作为参数传递给executor(executor 函数在Promise构造函数返回实例对象前被调用)。resolve 和 reject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。executor 内部通常会执行一些异步操作,一旦异步操作执行完毕(可能成功/失败),要么调用resolve函数来将promise状态改成fulfilled,要么调用reject 函数将promise的状态改为rejected。如果在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。
实例方法:
Promise.prototype.then(fun1(x),fun2(x))
该方法接受两个函数作为参数,promise的状态为成功时调用第一个参数,失败时调用第二个参数。也就是当resolve函数被成功调用时,触发then的第一个参数,当reject函数被调用时,触发then的第二个参数。
每个回调也都接受一个参数,分别为resolve和reject函数被调用时传入的参数。
then方法返回一个新的Promise对象,注意,是新的!
栗子:
当我传入1时,resolve执行(只要它执行了就代表成功了),看下控制台输出:
逻辑分析:执行promise ---> resolve函数执行 ---> then的第一个回调执行 ---> 返回一个新的promise对象 ---> then的第一个回调执行
看下例是如何失败的:
当我传入9999时,reject函数被调用(它被调用就代表失败了),看控制台输出:
逻辑分析:执行promise ---> reject函数执行 ---> then的第二个回调执行 ---> 返回一个新的promise对象 ---> then的第一个回调执行
划重点:
promise明明失败了,为什么第二个then的第一个回调执行而不是第二个呢?因为then返回的是一个新的promise对象,和被传入9999执行的函数返回的不是同一个promise。此时也就是说新的promise的状态为成功,但如果第一个then的某个回调执行后发生错误,第二个then的第二个回调就会调用了,因为这是新的promise失败了。
对于新人纠结的问题(就是本人):这tm成功失败不就是if else控制的吗?
见下例:
我擦?我干你大爷是什么鬼?见控制台输出:
逻辑分析:执行promise ---> 报错了!!! 默认调用reject函数,参数为抛出的错误对象 ---> then的第二个回调执行 ---> 返回一个新的promise对象 ---> then的第一个回调执行
结论:发生错误会自动调用reject,传入的参数是错误对象
Promise.prototype.catch(fun(x))
该方法接受一个函数作为参数,在失败时调用,也就是当reject函数被调用时触发该方法。也就是说它也能接收promise的失败状态,并执行回调函数,回调的参数为reject函数被调用时的传入的参数。见下例:
如果promise抛出错误,比如上面那个‘我是你大爷’,也会执行catch
还有,如果then的回调发生错误,catch同样执行。
PS:catch后面接的then,回调函数内的console.log输出的内容我手误了,你可以看成我接收到catch回调传给我的参数是......
关于承若:
promise就是承若,说一不二,何为说以不二?见下例:
当resolve执行,状态就为成功,此后状态就不变了,我们看到后面跟了一个我干你大爷,但是状态没变。这就是承若。
我们发现,控制台第一个出现的是一个'promise',然后才是then的第一个回调执行。这就是此文一开始说的promise的特点。
Promise.all方法用于将多个 Promise 实例,包装成一个新的 Promise 实例,接受一个数组作为参数,数组成员需要是promise对象,若不是,会转。数组成员全部成功,那么新Promise实例则成功,有一个失败,那就失败。若成功,resolve的参数是一个数组,成员为数组中成员的成功结果。弱失败,reject的参数就是失败成员的结果。
Promise.race方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。只要有一个实例率先改变状态,新Promise的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给新Promise的回调函数。
Promise.resolve方法将参数转为Promise对象。
1.如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。
2.参数是一个thenable对象,Promise.resolve方法会将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。thenable的执行结果会做为Promise对象的resolve的参数。见下例:
如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的 Promise 对象,状态为resolved。参数为resolve的参数。
Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。注意,Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。这一点与Promise.resolve方法不一致。
MDN
MDN
阮师傅