PromisePromise就像这个词的表层意识,表达的是一种承诺,承诺,之后会给出一个结果,成功或者失败。现在已经成为主流的异步编程操作方式并写入标准。状态Promise有一种且只有三种状态:待定(pending):初始状态,既没有实现也没有被拒绝。Fulfilled:表示操作成功完成。Rejected:表示操作失败。其实我觉得这个模型还是挺简单易懂的。就像,你向你的女朋友求婚,她告诉你她要考虑一下,明天给你答案。这是一个承诺。同时,这也是一个等待的过程(pending),然后你等到你女朋友明天给你一个答复,同意(fulfilled)或者拒绝(rejected),如果同意,就准备结婚,如果你不同意,等下次再Propose吧,哈哈哈。应该如何改变状态?Promise的构造函数需要传入一个函数执行器。这个函数需要两个输入参数,resolve和rejected。这两个方法主要用于修改状态。当我们调用resolve函数时,Promise的状态变为fulfilled。当我们调用reject函数时,Promise的状态变为reject。例如:newPromise((resolve,reject)=>{console.log("开始求婚。")console.log("...")console.log("考虑一下。")setTimeout(()=>{if(isHandsome||isRich){resolve('我同意!')}else{reject("拒绝:我们不同意")}},2000)})这里还有一点需要注意,如果promisehasisfulfilledorrejected,那么我们也可以说它处于一个settled状态。链式调用和Rx很像,也是链式调用。这样做的好处是异步逻辑更清晰、连贯、直观,避免了回调地狱。我们可以使用Promise.then()、Promise.catch()和Promise.finally()方法将进一步的操作与即将完成的Promise相关联。这些方法还返回一个新生成的Promise对象,可以选择像这样链接:constmyPromise=(newPromise(myExecutorFunc)).then(handleFulfilledA,handleRejectedA).then(handleFulfilledB,handleRejectedB).then(handleFulfilledC,handleRejectedC);//或者,这可能会更好...我们一般推荐使用第二种写法,因为如果第一种写法中间出错,在.then中处理完后,会继续到.then的下一个onfulfilled函数,不直观。当然,如果你有立即处理异常的需求,也可以这样写。当.then()中没有可以返回Promise对象的函数时,链式调用会直接进入下一个循环。因此,链式调用可以省略最后一个.catch()之前的所有handleRejections。同样,.catch()实际上只是.then(),没有为handleFulfilled保留的参数位置。它仍然是一个承诺。这里有一个特别需要注意的地方。Promise.then(),Promise.catch(),Promise.finally()这些方法会返回一个新的Promise,这在其他很多文章中都会被忽略。.then()函数最终会返回一个Promise。如果在.then的onfulfilled(即入参第一个函数)中返回了一个值或对象,则Promise的状态会被确定(settled),然后在接下来的.then(),并将此值或对象作为输入参数传入。嘿,等等,如果你只是在.then()中返回了一个Promise怎么办?这时候返回的Promise会被直接替换掉。它与RxJava中的flatMap操作非常相似。MDN中是这样解释的:链式调用中的promise就像俄罗斯套娃,是嵌套的,但又像栈一样,每一个都要从最上面弹出。链中的第一个承诺是嵌套最深的,将最先弹出。(promiseD,(promiseC,(promiseB,(promiseA))))当有nextValue是promise时,会出现动态替换效果。return将导致promise弹出,但nextValuepromise将被推入弹出的promise的位置。对于上面显示的嵌套场景,假设与“promiseB”关联的.then()返回值为“promiseX”的nextValue。所以嵌套结果看起来像这样:(promiseD,(promiseC,(promiseX)))观察者模式?而且一个Promise可能会参与多个嵌套,感觉也是一种观察者模式,支持多个观察者。对于下面的代码,promiseA到“已解决”状态的转换会导致在两个实例上调用.then。constpromiseA=newPromise(myExecutorFunc);constpromiseB=promiseA.then(handleFulfilled1,handleRejected1);constpromiseC=promiseA.then(handleFulfilled2,handleRejected2);写点代码说了这么多,写点代码,就写一个,女朋友看到你的诚意,多次拒绝,最后同意的故事。手动狗头。letcount=0constpropose=()=>{returnnewPromise((resolve,reject)=>{console.log("开始提议。")console.log("...")console.log("think关于它。")setTimeout(()=>{if(count<3){reject("拒绝:我们不同意")count++}else{resolve('我同意!')}},2000)})}conststartPropose=()=>{propose().then((result)=>{console.log(result)console.log("EndSahua")console.log(",·,·,,·,·,·,")},).catch((e)=>{{console.error(e)console.log("已拒绝,请下次提议。")setTimeout(()=>{startPropose()},3000)}})}startPropose()补充:有一些小细节,Promise一旦创建,传入的executor会立即执行,一个处于“settled”状态的Promise也可以接受操作,即,后面可以跟一个then或catch函数。所有Promise都是异步的,即使是“已解决”的Promises。在已经处于“已解决”状态的promise中的操作只有在清除promise链调用堆栈并且事件循环结束后才会执行。这效果与setTimeout(action,10)非常相似。constpromiseA=newPromise((resolutionFunc,rejectionFunc)=>{resolutionFunc(777);});//至此,“promiseA”已经解析完毕。promiseA.then((val)=>console.log("asynchronouslogginghasval:",val));console.log("immediatelogging");//按以下顺序生成输出://immediatelogging//asynchronouslogginghasval:777其他一些静态方法Promise.all(iterable)该方法返回一个新的promise对象,只有iterable参数对象中的promise对象全部成功时promise对象才会触发成功,一旦有任何可迭代的如果里面的promise对象失败,promise对象的失败会立即被触发。新的promise对象触发成功状态后,会取一个包含iterable中所有promise返回值的数组作为成功回调的返回值,顺序与iterable的顺序一致;如果新的promise对象触发了失败状态,它会把iterable中第一个失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常用于处理多个promise对象的状态集合。(可以参考jQuery.when方法---译者注)Promise.allSettled(iterable)等到所有的promises都完成(settled)(每个promise都被fulfilled(完成)或rejected(拒绝))。返回一个承诺,当所有承诺都得到履行时,该承诺就会履行。并使用一组对象,每个对象对应一个promise的结果。Promise.any(iterable)接受Promise对象的集合,当其中一个promise成功时,它返回该成功promise的值。Promise.race(iterable)当iterable参数中的任何一个childpromise成功或失败时,parentpromise会立即以childpromise的成功返回值或失败详情为参数调用父promise绑定的对应handle,并且返回承诺对象。Promise.reject(reason)返回一个状态为失败的Promise对象,并将给定的失败信息传递给相应的处理方法。Promise.resolve(value)返回一个Promise对象,其状态由给定值决定。如果该值是thenable(即具有then方法的对象),则返回的Promise对象的最终状态由then方法的执行决定;otherwise(值为空,基本类型或没有then方法的对象),返回的PromisePromise对象的状态为fulfilled,将value传递给对应的then方法。一般来说,如果你不知道一个值是否是一个Promise对象,使用Promise.resolve(value)返回一个Promise对象,这样这个值就可以作为一个Promise对象。参考:MDN(https://developer.mozilla.org...
