awesome-interview/assets/js/605371c8.b7d336b2.js

1 line
33 KiB
JavaScript

"use strict";(self.webpackChunkjjbook=self.webpackChunkjjbook||[]).push([[2299],{3905:function(e,n,t){t.d(n,{Zo:function(){return u},kt:function(){return d}});var r=t(7294);function o(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function i(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function l(e){for(var n=1;n<arguments.length;n++){var t=null!=arguments[n]?arguments[n]:{};n%2?i(Object(t),!0).forEach((function(n){o(e,n,t[n])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(t)):i(Object(t)).forEach((function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(t,n))}))}return e}function s(e,n){if(null==e)return{};var t,r,o=function(e,n){if(null==e)return{};var t,r,o={},i=Object.keys(e);for(r=0;r<i.length;r++)t=i[r],n.indexOf(t)>=0||(o[t]=e[t]);return o}(e,n);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(r=0;r<i.length;r++)t=i[r],n.indexOf(t)>=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=r.createContext({}),a=function(e){var n=r.useContext(c),t=n;return e&&(t="function"==typeof e?e(n):l(l({},n),e)),t},u=function(e){var n=a(e.components);return r.createElement(c.Provider,{value:n},e.children)},f={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},p=r.forwardRef((function(e,n){var t=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,u=s(e,["components","mdxType","originalType","parentName"]),p=a(t),d=o,m=p["".concat(c,".").concat(d)]||p[d]||f[d]||i;return t?r.createElement(m,l(l({ref:n},u),{},{components:t})):r.createElement(m,l({ref:n},u))}));function d(e,n){var t=arguments,o=n&&n.mdxType;if("string"==typeof e||o){var i=t.length,l=new Array(i);l[0]=p;var s={};for(var c in n)hasOwnProperty.call(n,c)&&(s[c]=n[c]);s.originalType=e,s.mdxType="string"==typeof e?e:o,l[1]=s;for(var a=2;a<i;a++)l[a]=t[a];return r.createElement.apply(null,l)}return r.createElement.apply(null,t)}p.displayName="MDXCreateElement"},7643:function(e,n,t){t.r(n),t.d(n,{frontMatter:function(){return s},contentTitle:function(){return c},metadata:function(){return a},toc:function(){return u},default:function(){return p}});var r=t(7462),o=t(3366),i=(t(7294),t(3905)),l=["components"],s={sidebar_label:"\u7f16\u7801\uff1a\u5b9e\u73b0\u4e00\u4e2a Promises/A+",sidebar_position:10},c="\u5b9e\u73b0\u4e00\u4e2a Promises/A+ \u89c4\u8303\u7684 Promise",a={unversionedId:"book1/coding-promise",id:"book1/coding-promise",isDocsHomePage:!1,title:"\u5b9e\u73b0\u4e00\u4e2a Promises/A+ \u89c4\u8303\u7684 Promise",description:"\u8fd9\u662f\u4e00\u9053\u6709\u7740\u6210\u719f\u7684\u4e1a\u754c\u89c4\u8303\u7684 coding \u9898\uff0c\u5b8c\u6210\u8fd9\u9053\u9898\u7684\u524d\u7f6e\u77e5\u8bc6\u5c31\u662f\u8981\u4e86\u89e3\u4ec0\u4e48\u662f Promises/A+\u3002",source:"@site/docs/book1/coding-promise.md",sourceDirName:"book1",slug:"/book1/coding-promise",permalink:"/awesome-interview/book1/coding-promise",tags:[],version:"current",sidebarPosition:10,frontMatter:{sidebar_label:"\u7f16\u7801\uff1a\u5b9e\u73b0\u4e00\u4e2a Promises/A+",sidebar_position:10},sidebar:"tutorialSidebar",previous:{title:"\u7f51\u7edc\uff1a\u524d\u7aef\u5b89\u5168",permalink:"/awesome-interview/book1/network-security"},next:{title:"\u7b97\u6cd5\uff1a\u5e73\u8861\u4e8c\u53c9\u6811",permalink:"/awesome-interview/book1/algorithm-balanced-binary-trees"}},u=[{value:"\u7f16\u5199\u4ee3\u7801",id:"\u7f16\u5199\u4ee3\u7801",children:[{value:"1. \u57fa\u7840\u6846\u67b6",id:"1-\u57fa\u7840\u6846\u67b6",children:[]},{value:"2. then \u65b9\u6cd5",id:"2-then-\u65b9\u6cd5",children:[]},{value:"3. Promise \u5904\u7406\u7a0b\u5e8f",id:"3-promise-\u5904\u7406\u7a0b\u5e8f",children:[]},{value:"4. \u5b8c\u6574\u4ee3\u7801",id:"4-\u5b8c\u6574\u4ee3\u7801",children:[]}]},{value:"\u6d4b\u8bd5\u4ee3\u7801",id:"\u6d4b\u8bd5\u4ee3\u7801",children:[{value:"1. \u66b4\u9732\u4e00\u4e2a\u7b80\u5355\u7684\u9002\u914d\u5668\u63a5\u53e3",id:"1-\u66b4\u9732\u4e00\u4e2a\u7b80\u5355\u7684\u9002\u914d\u5668\u63a5\u53e3",children:[]},{value:"2. \u8fd0\u884c\u547d\u4ee4",id:"2-\u8fd0\u884c\u547d\u4ee4",children:[]},{value:"3. \u6d4b\u8bd5\u7ed3\u679c",id:"3-\u6d4b\u8bd5\u7ed3\u679c",children:[]}]},{value:"\u53c2\u8003\u8d44\u6599",id:"\u53c2\u8003\u8d44\u6599",children:[]}],f={toc:u};function p(e){var n=e.components,t=(0,o.Z)(e,l);return(0,i.kt)("wrapper",(0,r.Z)({},f,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h1",{id:"\u5b9e\u73b0\u4e00\u4e2a-promisesa-\u89c4\u8303\u7684-promise"},"\u5b9e\u73b0\u4e00\u4e2a Promises/A+ \u89c4\u8303\u7684 Promise"),(0,i.kt)("p",null,"\u8fd9\u662f\u4e00\u9053\u6709\u7740\u6210\u719f\u7684\u4e1a\u754c\u89c4\u8303\u7684 coding \u9898\uff0c\u5b8c\u6210\u8fd9\u9053\u9898\u7684\u524d\u7f6e\u77e5\u8bc6\u5c31\u662f\u8981\u4e86\u89e3\u4ec0\u4e48\u662f ",(0,i.kt)("a",{parentName:"p",href:"https://promisesaplus.com"},"Promises/A+"),"\u3002"),(0,i.kt)("p",null,"\u8fd9\u9053\u9898\u7684\u96be\u70b9\u5c31\u5728\u4e8e\u5b83\u662f\u6709\u89c4\u8303\u7684\uff0c\u4efb\u4f55\u4e00\u4e2a\u4e0d\u6ee1\u8db3\u6240\u6709\u89c4\u8303\u6761\u4ef6\u7684\u89e3\u7b54\u90fd\u662f\u9519\u8bef\u7684\u3002\u540c\u65f6\uff0c\u6210\u719f\u7684\u89c4\u8303\u4e5f\u914d\u5957\u4e86\u6210\u719f\u7684",(0,i.kt)("a",{parentName:"p",href:"https://github.com/promises-aplus/promises-tests"},"\u6d4b\u8bd5\u7528\u4f8b"),"\uff0c\u5b98\u65b9\u63d0\u4f9b\u4e86 872 \u4e2a\u6d4b\u8bd5\u7528\u4f8b\u9488\u5bf9\u89c4\u8303\u4e2d\u7684\u6240\u6709\u6761\u4ef6\u4e00\u4e00\u8fdb\u884c\u68c0\u6d4b\uff0c\u54ea\u6015\u53ea\u6709\u4e00\u6761\u5931\u8d25\uff0c\u90a3\u4e5f\u662f\u9519\u8bef\u7684\u89e3\u7b54\u3002"),(0,i.kt)("p",null,"\u800c\u8fd9\u9053\u9898\u7684\u7b54\u9898\u5173\u952e\u4e5f\u6070\u6070\u662f\u56e0\u4e3a\u5b83\u662f\u6709\u89c4\u8303\u7684\uff0c\u53ea\u8981\u6211\u4eec\u5bf9\u4e8e\u89c4\u8303\u4e86\u7136\u4e8e\u80f8\uff0c\u90a3\u4e48\u7f16\u5199\u4ee3\u7801\u81ea\u7136\u4e5f\u662f\u6c34\u5230\u6e20\u6210\u3002\u56e0\u4e3a\u5b98\u65b9\u89c4\u8303\u63d0\u4f9b\u4e86\u4e00\u4e2a\u7b26\u5408 Promises/A+ \u89c4\u8303\u7684 Promise \u5e94\u8be5\u5177\u6709\u7684\u5168\u90e8\u6761\u4ef6\uff0c\u5e76\u4e14\u5728 ",(0,i.kt)("a",{parentName:"p",href:"https://promisesaplus.com/#requirements"},"Requirements")," \u4e00\u8282\u4e2d\u7ed3\u6784\u6e05\u6670\u3001\u903b\u8f91\u5145\u5206\u7684\u8868\u8ff0\u4e86\u51fa\u6765\uff0c\u6211\u4eec\u53ea\u9700\u5c06\u89c4\u8303\u4e2d\u7684\u6587\u5b57\u8f6c\u53d8\u4e3a\u4ee3\u7801\uff0c\u5c31\u80fd\u591f\u5b9e\u73b0\u4e00\u4e2a Promises/A+ \u89c4\u8303\u7684 Promise\u3002"),(0,i.kt)("h2",{id:"\u7f16\u5199\u4ee3\u7801"},"\u7f16\u5199\u4ee3\u7801"),(0,i.kt)("p",null,"\u56e0\u4e3a\u89c4\u8303\u6761\u4f8b\u8f83\u591a\uff0c\u6211\u4eec\u62c6\u89e3\u6210\u4e09\u5757\u6765\u7406\u89e3\u8bb0\u5fc6\uff0c\u5206\u522b\u662f\uff1a\u57fa\u7840\u6846\u67b6\u3001then \u65b9\u6cd5\u548c Promise \u5904\u7406\u7a0b\u5e8f\u3002"),(0,i.kt)("p",null,"\u6bcf\u4e00\u5757\u7531\u4e24\u90e8\u5206\u6784\u6210\uff1a"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"\u6d41\u7a0b\u56fe\uff1a\u5c55\u793a\u4e86\u4ee3\u7801\u903b\u8f91\u7684\u5173\u952e\u6b65\u9aa4\uff0c\u4e5f\u662f\u4f18\u5148\u9700\u8981\u7406\u89e3\u8bb0\u5fc6\u7684\u70b9\u3002"),(0,i.kt)("li",{parentName:"ul"},"\u5b9e\u73b0\u4ee3\u7801\uff1a\u5c55\u793a\u4e86\u4ee3\u7801\u903b\u8f91\u7684\u5177\u4f53\u7ec6\u8282\uff0c\u662f\u5bf9\u5173\u952e\u6b65\u9aa4\u7684\u5b8c\u5584\u8865\u5168\u3002")),(0,i.kt)("p",null,"\u5176\u4e2d\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u6d89\u53ca\u5230\u89c4\u8303\u6761\u4f8b\u7684\u70b9\u4f1a\u6ce8\u660e\u89c4\u8303\u5e8f\u53f7"),"\u3002"),(0,i.kt)("p",null,"\u518d\u6b21\u5f3a\u8c03\uff0c",(0,i.kt)("strong",{parentName:"p"},"\u672c\u9898\u7684\u7b54\u9898\u5173\u952e\u662f\u719f\u6089\u89c4\u8303"),"\uff01\u78e8\u5200\u4e0d\u8bef\u780d\u67f4\u5de5\uff0c\u52a1\u5fc5\u5148\u719f\u6089\uff01\u719f\u6089\uff01\u719f\u6089\uff01"),(0,i.kt)("h3",{id:"1-\u57fa\u7840\u6846\u67b6"},"1. \u57fa\u7840\u6846\u67b6"),(0,i.kt)("h4",{id:"11-\u6d41\u7a0b\u56fe"},"1.1 \u6d41\u7a0b\u56fe"),(0,i.kt)("p",null,(0,i.kt)("img",{parentName:"p",src:"https://user-images.githubusercontent.com/17525377/125752900-dbddfdf6-73a6-4645-a35e-765c3cbf45f8.jpg",alt:"\u57fa\u672c\u6846\u67b6"})),(0,i.kt)("h4",{id:"12-\u5b9e\u73b0\u4ee3\u7801"},"1.2 \u5b9e\u73b0\u4ee3\u7801"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-js"},'function Promise(executor) {\n // 2.1. Promise \u7684\u72b6\u6001\n // Promise \u5fc5\u987b\u5904\u4e8e\u4ee5\u4e0b\u4e09\u79cd\u72b6\u6001\u4e4b\u4e00\uff1apending\uff0cfulfilled \u6216\u8005 rejected\u3002\n this.state = "pending";\n // 2.2.6.1. \u5982\u679c promise \u5904\u4e8e fulfilled \u72b6\u6001\uff0c\u6240\u6709\u76f8\u5e94\u7684 onFulfilled \u56de\u8c03\u5fc5\u987b\u6309\u7167\u5b83\u4eec\u5bf9\u5e94\u7684 then \u7684\u539f\u59cb\u8c03\u7528\u987a\u5e8f\u6765\u6267\u884c\u3002\n this.onFulfilledCallback = [];\n // 2.2.6.2. \u5982\u679c promise \u5904\u4e8e rejected \u72b6\u6001\uff0c\u6240\u6709\u76f8\u5e94\u7684 onRejected \u56de\u8c03\u5fc5\u987b\u6309\u7167\u5b83\u4eec\u5bf9\u5e94\u7684 then \u7684\u539f\u59cb\u8c03\u7528\u987a\u5e8f\u6765\u6267\u884c\u3002\n this.onRejectedCallback = [];\n\n const self = this;\n\n function resolve(value) {\n setTimeout(function () {\n // 2.1.1. \u5f53 Promise \u5904\u4e8e pending \u72b6\u6001\u65f6\uff1a\n // 2.1.1.1. \u53ef\u4ee5\u8f6c\u6362\u5230 fulfilled \u6216 rejected \u72b6\u6001\u3002\n // 2.1.2. \u5f53 Promise \u5904\u4e8e fulfilled \u72b6\u6001\u65f6\uff1a\n // 2.1.2.1. \u4e0d\u5f97\u8fc7\u6e21\u5230\u4efb\u4f55\u5176\u4ed6\u72b6\u6001\u3002\n // 2.1.2.2. \u5fc5\u987b\u6709\u4e00\u4e2a\u4e0d\u80fd\u6539\u53d8\u7684\u503c\u3002\n if (self.state === "pending") {\n self.state = "fulfilled";\n self.data = value;\n // 2.2.6.1. \u5982\u679c promise \u5904\u4e8e fulfilled \u72b6\u6001\uff0c\u6240\u6709\u76f8\u5e94\u7684 onFulfilled \u56de\u8c03\u5fc5\u987b\u6309\u7167\u5b83\u4eec\u5bf9\u5e94\u7684 then \u7684\u539f\u59cb\u8c03\u7528\u987a\u5e8f\u6765\u6267\u884c\u3002\n for (let i = 0; i < self.onFulfilledCallback.length; i++) {\n self.onFulfilledCallback[i](value);\n }\n }\n });\n }\n\n function reject(reason) {\n setTimeout(function () {\n // 2.1.1. \u5f53 Promise \u5904\u4e8e pending \u72b6\u6001\u65f6\uff1a\n // 2.1.1.1. \u53ef\u4ee5\u8f6c\u6362\u5230 fulfilled \u6216 rejected \u72b6\u6001\u3002\n // 2.1.3. \u5f53 Promise \u5904\u4e8e rejected \u72b6\u6001\u65f6\uff1a\n // 2.1.2.1. \u4e0d\u5f97\u8fc7\u6e21\u5230\u4efb\u4f55\u5176\u4ed6\u72b6\u6001\u3002\n // 2.1.2.2. \u5fc5\u987b\u6709\u4e00\u4e2a\u4e0d\u80fd\u6539\u53d8\u7684\u503c\u3002\n if (self.state === "pending") {\n self.state = "rejected";\n self.data = reason;\n // 2.2.6.2. \u5982\u679c promise \u5904\u4e8e rejected \u72b6\u6001\uff0c\u6240\u6709\u76f8\u5e94\u7684 onRejected \u56de\u8c03\u5fc5\u987b\u6309\u7167\u5b83\u4eec\u5bf9\u5e94\u7684 then \u7684\u539f\u59cb\u8c03\u7528\u987a\u5e8f\u6765\u6267\u884c\u3002\n for (let i = 0; i < self.onRejectedCallback.length; i++) {\n self.onRejectedCallback[i](reason);\n }\n }\n });\n }\n\n // \u8865\u5145\u8bf4\u660e\uff1a\u7528\u6237\u4f20\u5165\u7684\u51fd\u6570\u53ef\u80fd\u4e5f\u4f1a\u6267\u884c\u5f02\u5e38\uff0c\u6240\u4ee5\u8fd9\u91cc\u7528 try...catch \u5305\u88f9\n try {\n executor(resolve, reject);\n } catch (reason) {\n reject(reason);\n }\n}\n')),(0,i.kt)("h3",{id:"2-then-\u65b9\u6cd5"},"2. then \u65b9\u6cd5"),(0,i.kt)("h4",{id:"21-\u6d41\u7a0b\u56fe"},"2.1 \u6d41\u7a0b\u56fe"),(0,i.kt)("p",null,(0,i.kt)("img",{parentName:"p",src:"https://user-images.githubusercontent.com/17525377/125584242-610b4e49-cd26-42d4-a09c-f2ec831c98b7.jpg",alt:"then \u65b9\u6cd5"})),(0,i.kt)("h4",{id:"22-\u5b9e\u73b0\u4ee3\u7801"},"2.2 \u5b9e\u73b0\u4ee3\u7801"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-js"},'// 2.2. then \u65b9\u6cd5\n// \u4e00\u4e2a promise \u5fc5\u987b\u63d0\u4f9b\u4e00\u4e2a then \u65b9\u6cd5\u6765\u8bbf\u95ee\u5176\u5f53\u524d\u503c\u6216\u6700\u7ec8\u503c\u6216 rejected \u7684\u539f\u56e0\u3002\n// \u4e00\u4e2a promise \u7684 then \u65b9\u6cd5\u63a5\u53d7\u4e24\u4e2a\u53c2\u6570\uff1a\n// promise.then(onFulfilled, onRejected)\nPromise.prototype.then = function (onFulfilled, onRejected) {\n const self = this;\n\n let promise2;\n // 2.2.7. then \u5fc5\u987b\u8fd4\u56de\u4e00\u4e2a promise\n return (promise2 = new Promise(function (resolve, reject) {\n // 2.2.2. \u5982\u679c onFulfilled \u662f\u4e00\u4e2a\u51fd\u6570:\n // 2.2.2.1. \u5b83\u5fc5\u987b\u5728 promise \u7684\u72b6\u6001\u53d8\u4e3a fulfilled \u540e\u88ab\u8c03\u7528\uff0c\u5e76\u5c06 promise \u7684\u503c\u4f5c\u4e3a\u5b83\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\n // 2.2.2.2. \u5b83\u4e00\u5b9a\u4e0d\u80fd\u5728 promise \u7684\u72b6\u6001\u53d8\u4e3a fulfilled \u524d\u88ab\u8c03\u7528\u3002\n // 2.2.2.3. \u5b83\u6700\u591a\u53ea\u80fd\u88ab\u8c03\u7528\u4e00\u6b21\u3002\n if (self.state === "fulfilled") {\n // 2.2.4. onFulfilled \u6216 onRejected \u5728\u6267\u884c\u4e0a\u4e0b\u6587\u5806\u6808\u4ec5\u5305\u542b\u5e73\u53f0\u4ee3\u7801\u4e4b\u524d\u4e0d\u5f97\u8c03\u7528\u3002\n // 3.1. \u8fd9\u53ef\u4ee5\u901a\u8fc7\u201c\u5b8f\u4efb\u52a1\u201d\u673a\u5236\uff08\u4f8b\u5982 setTimeout \u6216 setImmediate\uff09\u6216\u201c\u5fae\u4efb\u52a1\u201d\u673a\u5236\uff08\u4f8b\u5982 MutationObserver \u6216 process.nextTick\uff09\u6765\u5b9e\u73b0\u3002\n setTimeout(function () {\n // 2.2.1. onFulfilled \u548c onRejected \u90fd\u662f\u53ef\u9009\u53c2\u6570\uff1a\n // 2.2.1.1. \u5982\u679c onFulfilled \u4e0d\u662f\u4e00\u4e2a\u51fd\u6570\uff0c\u5b83\u5fc5\u987b\u88ab\u5ffd\u7565\u3002\n if (typeof onFulfilled === "function") {\n try {\n // 2.2.2.1. \u5b83\u5fc5\u987b\u5728 promise \u7684\u72b6\u6001\u53d8\u4e3a fulfilled \u540e\u88ab\u8c03\u7528\uff0c\u5e76\u5c06 promise \u7684\u503c\u4f5c\u4e3a\u5b83\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\n // 2.2.5. onFulfilled \u548c onRejected \u5fc5\u987b\u4f5c\u4e3a\u51fd\u6570\u8c03\u7528\u3002\n const x = onFulfilled(self.data);\n // 2.2.7.1. \u5982\u679c onFulfilled \u6216 onRejected \u8fd4\u56de\u4e86\u4e00\u4e2a\u503c x\uff0c\u5219\u8fd0\u884c Promise \u5904\u7406\u7a0b\u5e8f [[Resolve]](promise2, x)\u3002\n promiseResolutionProcedure(promise2, x, resolve, reject);\n } catch (e) {\n // 2.2.7.2. \u5982\u679c onFulfilled \u6216 onRejected \u629b\u51fa\u4e86\u4e00\u4e2a\u5f02\u5e38\uff0cpromise2 \u5fc5\u987b\u7528 e \u4f5c\u4e3a reason \u6765\u53d8\u4e3a rejected \u72b6\u6001\u3002\n reject(e);\n }\n } else {\n // 2.2.7.3. \u5982\u679c onFulfilled \u4e0d\u662f\u4e00\u4e2a\u51fd\u6570\u4e14 promise1 \u4e3a fulfilled \u72b6\u6001\uff0cpromise2 \u5fc5\u987b\u7528\u548c promise1 \u4e00\u6837\u7684\u503c\u6765\u53d8\u4e3a fulfilled \u72b6\u6001\u3002\n resolve(self.data);\n }\n });\n }\n // 2.2.3. \u5982\u679c onRejected \u662f\u4e00\u4e2a\u51fd\u6570\uff0c\n // 2.2.3.1. \u5b83\u5fc5\u987b\u5728 promise \u7684\u72b6\u6001\u53d8\u4e3a rejected \u540e\u88ab\u8c03\u7528\uff0c\u5e76\u5c06 promise \u7684 reason \u4f5c\u4e3a\u5b83\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\n // 2.2.3.2. \u5b83\u4e00\u5b9a\u4e0d\u80fd\u5728 promise \u7684\u72b6\u6001\u53d8\u4e3a rejected \u524d\u88ab\u8c03\u7528\u3002\n // 2.2.3.3. \u5b83\u6700\u591a\u53ea\u80fd\u88ab\u8c03\u7528\u4e00\u6b21\u3002\n else if (self.state === "rejected") {\n // 2.2.4. onFulfilled \u6216 onRejected \u5728\u6267\u884c\u4e0a\u4e0b\u6587\u5806\u6808\u4ec5\u5305\u542b\u5e73\u53f0\u4ee3\u7801\u4e4b\u524d\u4e0d\u5f97\u8c03\u7528\u3002\n // 3.1. \u8fd9\u53ef\u4ee5\u901a\u8fc7\u201c\u5b8f\u4efb\u52a1\u201d\u673a\u5236\uff08\u4f8b\u5982 setTimeout \u6216 setImmediate\uff09\u6216\u201c\u5fae\u4efb\u52a1\u201d\u673a\u5236\uff08\u4f8b\u5982 MutationObserver \u6216 process.nextTick\uff09\u6765\u5b9e\u73b0\u3002\n setTimeout(function () {\n // 2.2.1. onFulfilled \u548c onRejected \u90fd\u662f\u53ef\u9009\u53c2\u6570\uff1a\n // 2.2.1.2. \u5982\u679c onRejected \u4e0d\u662f\u4e00\u4e2a\u51fd\u6570\uff0c\u5b83\u5fc5\u987b\u88ab\u5ffd\u7565\u3002\n if (typeof onRejected === "function") {\n try {\n // 2.2.3.1. \u5b83\u5fc5\u987b\u5728 promise \u7684\u72b6\u6001\u53d8\u4e3a rejected \u540e\u88ab\u8c03\u7528\uff0c\u5e76\u5c06 promise \u7684 reason \u4f5c\u4e3a\u5b83\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\n // 2.2.5. onFulfilled \u548c onRejected \u5fc5\u987b\u4f5c\u4e3a\u51fd\u6570\u8c03\u7528\u3002\n const x = onRejected(self.data);\n // 2.2.7.1. \u5982\u679c onFulfilled \u6216 onRejected \u8fd4\u56de\u4e86\u4e00\u4e2a\u503c x\uff0c\u5219\u8fd0\u884c Promise \u5904\u7406\u7a0b\u5e8f [[Resolve]](promise2, x)\u3002\n promiseResolutionProcedure(promise2, x, resolve, reject);\n } catch (e) {\n // 2.2.7.2. \u5982\u679c onFulfilled \u6216 onRejected \u629b\u51fa\u4e86\u4e00\u4e2a\u5f02\u5e38\uff0cpromise2 \u5fc5\u987b\u7528 e \u4f5c\u4e3a reason \u6765\u53d8\u4e3a rejected \u72b6\u6001\u3002\n reject(e);\n }\n }\n // 2.2.7.4. \u5982\u679c onRejected \u4e0d\u662f\u4e00\u4e2a\u51fd\u6570\u4e14 promise1 \u4e3a rejected \u72b6\u6001\uff0cpromise2 \u5fc5\u987b\u7528\u548c promise1 \u4e00\u6837\u7684 reason \u6765\u53d8\u4e3a rejected \u72b6\u6001\u3002\n else {\n reject(self.data);\n }\n });\n } else if (self.state === "pending") {\n // 2.2.6. then \u53ef\u80fd\u4f1a\u88ab\u540c\u4e00\u4e2a promise \u591a\u6b21\u8c03\u7528\u3002\n\n // 2.2.6.1. \u5982\u679c promise \u5904\u4e8e fulfilled \u72b6\u6001\uff0c\u6240\u6709\u76f8\u5e94\u7684 onFulfilled \u56de\u8c03\u5fc5\u987b\u6309\u7167\u5b83\u4eec\u5bf9\u5e94\u7684 then \u7684\u539f\u59cb\u8c03\u7528\u987a\u5e8f\u6765\u6267\u884c\u3002\n self.onFulfilledCallback.push(function (promise1Value) {\n if (typeof onFulfilled === "function") {\n try {\n // 2.2.2.1. \u5b83\u5fc5\u987b\u5728 promise \u7684\u72b6\u6001\u53d8\u4e3a fulfilled \u540e\u88ab\u8c03\u7528\uff0c\u5e76\u5c06 promise \u7684\u503c\u4f5c\u4e3a\u5b83\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\n // 2.2.5. onFulfilled \u548c onRejected \u5fc5\u987b\u4f5c\u4e3a\u51fd\u6570\u8c03\u7528\u3002\n const x = onFulfilled(self.data);\n // 2.2.7.1. \u5982\u679c onFulfilled \u6216 onRejected \u8fd4\u56de\u4e86\u4e00\u4e2a\u503c x\uff0c\u5219\u8fd0\u884c Promise \u5904\u7406\u7a0b\u5e8f [[Resolve]](promise2, x)\u3002\n promiseResolutionProcedure(promise2, x, resolve, reject);\n } catch (e) {\n // 2.2.7.2. \u5982\u679c onFulfilled \u6216 onRejected \u629b\u51fa\u4e86\u4e00\u4e2a\u5f02\u5e38\uff0cpromise2 \u5fc5\u987b\u7528 e \u4f5c\u4e3a reason \u6765\u53d8\u4e3a rejected \u72b6\u6001\u3002\n reject(e);\n }\n }\n // 2.2.7.3. \u5982\u679c onFulfilled \u4e0d\u662f\u4e00\u4e2a\u51fd\u6570\u4e14 promise1 \u4e3a fulfilled \u72b6\u6001\uff0cpromise2 \u5fc5\u987b\u7528\u548c promise1 \u4e00\u6837\u7684\u503c\u6765\u53d8\u4e3a fulfilled \u72b6\u6001\u3002\n else {\n resolve(promise1Value);\n }\n });\n // 2.2.6.2. \u5982\u679c promise \u5904\u4e8e rejected \u72b6\u6001\uff0c\u6240\u6709\u76f8\u5e94\u7684 onRejected \u56de\u8c03\u5fc5\u987b\u6309\u7167\u5b83\u4eec\u5bf9\u5e94\u7684 then \u7684\u539f\u59cb\u8c03\u7528\u987a\u5e8f\u6765\u6267\u884c\u3002\n self.onRejectedCallback.push(function (promise1Reason) {\n if (typeof onRejected === "function") {\n try {\n // 2.2.3.1. \u5b83\u5fc5\u987b\u5728 promise \u7684\u72b6\u6001\u53d8\u4e3a rejected \u540e\u88ab\u8c03\u7528\uff0c\u5e76\u5c06 promise \u7684 reason \u4f5c\u4e3a\u5b83\u7684\u7b2c\u4e00\u4e2a\u53c2\u6570\u3002\n // 2.2.5. onFulfilled \u548c onRejected \u5fc5\u987b\u4f5c\u4e3a\u51fd\u6570\u8c03\u7528\u3002\n const x = onRejected(self.data);\n // 2.2.7.1. \u5982\u679c onFulfilled \u6216 onRejected \u8fd4\u56de\u4e86\u4e00\u4e2a\u503c x\uff0c\u5219\u8fd0\u884c Promise \u5904\u7406\u7a0b\u5e8f [[Resolve]](promise2, x)\u3002\n promiseResolutionProcedure(promise2, x, resolve, reject);\n } catch (e) {\n // 2.2.7.2. \u5982\u679c onFulfilled \u6216 onRejected \u629b\u51fa\u4e86\u4e00\u4e2a\u5f02\u5e38\uff0cpromise2 \u5fc5\u987b\u7528 e \u4f5c\u4e3a reason \u6765\u53d8\u4e3a rejected \u72b6\u6001\u3002\n reject(e);\n }\n }\n // 2.2.7.4. \u5982\u679c onRejected \u4e0d\u662f\u4e00\u4e2a\u51fd\u6570\u4e14 promise1 \u4e3a rejected \u72b6\u6001\uff0cpromise2 \u5fc5\u987b\u7528\u548c promise1 \u4e00\u6837\u7684 reason \u6765\u53d8\u4e3a rejected \u72b6\u6001\u3002\n else {\n reject(promise1Reason);\n }\n });\n }\n }));\n};\n')),(0,i.kt)("h3",{id:"3-promise-\u5904\u7406\u7a0b\u5e8f"},"3. Promise \u5904\u7406\u7a0b\u5e8f"),(0,i.kt)("h4",{id:"31-\u6d41\u7a0b\u56fe"},"3.1 \u6d41\u7a0b\u56fe"),(0,i.kt)("p",null,(0,i.kt)("img",{parentName:"p",src:"https://user-images.githubusercontent.com/17525377/125584320-981ea98a-0342-4a78-92fe-494f91412102.jpg",alt:"Promise \u5904\u7406\u7a0b\u5e8f"})),(0,i.kt)("h4",{id:"32-\u5b9e\u73b0\u4ee3\u7801"},"3.2 \u5b9e\u73b0\u4ee3\u7801"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-js"},'// 2.3. Promise \u5904\u7406\u7a0b\u5e8f\n// Promise \u5904\u7406\u7a0b\u5e8f\u662f\u4e00\u4e2a\u5c06 promise \u548c value \u4f5c\u4e3a\u8f93\u5165\u7684\u62bd\u8c61\u64cd\u4f5c\uff0c\u6211\u4eec\u5c06\u5176\u8868\u793a\u4e3a [[Resolve]](promise, x)\u3002\n// \u8865\u5145\u8bf4\u660e\uff1a\u8fd9\u91cc\u6211\u4eec\u5c06 resolve \u548c reject \u4e5f\u4f20\u5165\u8fdb\u6765\uff0c\u56e0\u4e3a\u540e\u7eed\u8981\u6839\u636e\u4e0d\u540c\u7684\u903b\u8f91\u5bf9 promise \u6267\u884c fulfill \u6216 reject \u64cd\u4f5c\u3002\nfunction promiseResolutionProcedure(promise2, x, resolve, reject) {\n // 2.3.1. \u5982\u679c promise \u548c x \u5f15\u7528\u7684\u662f\u540c\u4e00\u4e2a\u5bf9\u8c61\uff0cpromise \u5c06\u4ee5\u4e00\u4e2a TypeError \u4f5c\u4e3a reason \u6765\u8fdb\u884c reject\u3002\n if (promise2 === x) {\n return reject(new TypeError("Chaining cycle detected for promise"));\n }\n\n // 2.3.2. \u5982\u679c x \u662f\u4e00\u4e2a promise\uff0c\u6839\u636e\u5b83\u7684\u72b6\u6001\uff1a\n if (x instanceof Promise) {\n // 2.3.2.1. \u5982\u679c x \u7684\u72b6\u6001\u4e3a pending\uff0cpromise \u5fc5\u987b\u4fdd\u6301 pending \u72b6\u6001\u76f4\u5230 x \u7684\u72b6\u6001\u53d8\u4e3a fulfilled \u6216 rejected\u3002\n if (x.state === "pending") {\n x.then(function (value) {\n promiseResolutionProcedure(promise2, value, resolve, reject);\n }, reject);\n }\n // 2.3.2.2. \u5982\u679c x \u7684\u72b6\u6001\u4e3a fulfilled\uff0c\u90a3\u4e48 promise \u4e5f\u7528\u540c\u6837\u7684\u503c\u6765\u6267\u884c fulfill \u64cd\u4f5c\u3002\n else if (x.state === "fulfilled") {\n resolve(x.data);\n }\n // 2.3.2.3. \u5982\u679c x \u7684\u72b6\u6001\u4e3a rejected\uff0c\u90a3\u4e48 promise \u4e5f\u7528\u540c\u6837\u7684 reason \u6765\u6267\u884c reject \u64cd\u4f5c\u3002\n else if (x.state === "rejected") {\n reject(x.data);\n }\n return;\n }\n\n // 2.3.3. \u9664\u6b64\u4e4b\u5916\uff0c\u5982\u679c x \u662f\u4e00\u4e2a\u5bf9\u8c61\u6216\u8005\u51fd\u6570\uff0c\n if (x && (typeof x === "object" || typeof x === "function")) {\n // 2.3.3.3.3. \u5982\u679c resolvePromise \u548c rejectPromise \u90fd\u88ab\u8c03\u7528\uff0c\u6216\u8005\u591a\u6b21\u8c03\u7528\u540c\u6837\u7684\u53c2\u6570\uff0c\u5219\u7b2c\u4e00\u6b21\u8c03\u7528\u4f18\u5148\uff0c\u4efb\u4f55\u4e4b\u540e\u7684\u8c03\u7528\u90fd\u5c06\u88ab\u5ffd\u7565\u3002\n let isCalled = false;\n\n try {\n // 2.3.3.1. \u58f0\u660e\u4e00\u4e2a then \u53d8\u91cf\u6765\u4fdd\u5b58 then\n let then = x.then;\n // 2.3.3.3. \u5982\u679c then \u662f\u4e00\u4e2a\u51fd\u6570\uff0c\u5c06 x \u4f5c\u4e3a this \u6765\u8c03\u7528\u5b83\uff0c\u7b2c\u4e00\u4e2a\u53c2\u6570\u4e3a resolvePromise\uff0c\u7b2c\u4e8c\u4e2a\u53c2\u6570\u4e3a rejectPromise\uff0c\u5176\u4e2d\uff1a\n if (typeof then === "function") {\n then.call(\n x,\n // 2.3.3.3.1. \u5047\u8bbe resolvePromise \u4f7f\u7528\u4e00\u4e2a\u540d\u4e3a y \u7684\u503c\u6765\u8c03\u7528\uff0c\u8fd0\u884c promise \u5904\u7406\u7a0b\u5e8f [[Resolve]](promise, y)\u3002\n function resolvePromise(y) {\n // 2.3.3.3.3. \u5982\u679c resolvePromise \u548c rejectPromise \u90fd\u88ab\u8c03\u7528\uff0c\u6216\u8005\u591a\u6b21\u8c03\u7528\u540c\u6837\u7684\u53c2\u6570\uff0c\u5219\u7b2c\u4e00\u6b21\u8c03\u7528\u4f18\u5148\uff0c\u4efb\u4f55\u4e4b\u540e\u7684\u8c03\u7528\u90fd\u5c06\u88ab\u5ffd\u7565\u3002\n if (isCalled) return;\n isCalled = true;\n return promiseResolutionProcedure(promise2, y, resolve, reject);\n },\n // 2.3.3.3.2. \u5047\u8bbe rejectPromise \u4f7f\u7528\u4e00\u4e2a\u540d\u4e3a r \u7684 reason \u6765\u8c03\u7528\uff0c\u5219\u7528 r \u4f5c\u4e3a reason \u5bf9 promise \u6267\u884c reject \u64cd\u4f5c\u3002\n function rejectPromise(r) {\n // 2.3.3.3.3. \u5982\u679c resolvePromise \u548c rejectPromise \u90fd\u88ab\u8c03\u7528\uff0c\u6216\u8005\u591a\u6b21\u8c03\u7528\u540c\u6837\u7684\u53c2\u6570\uff0c\u5219\u7b2c\u4e00\u6b21\u8c03\u7528\u4f18\u5148\uff0c\u4efb\u4f55\u4e4b\u540e\u7684\u8c03\u7528\u90fd\u5c06\u88ab\u5ffd\u7565\u3002\n if (isCalled) return;\n isCalled = true;\n return reject(r);\n }\n );\n }\n // 2.3.3.4. \u5982\u679c then \u4e0d\u662f\u4e00\u4e2a\u51fd\u6570\uff0c\u4f7f\u7528 x \u4f5c\u4e3a\u503c\u5bf9 promise \u6267\u884c fulfill \u64cd\u4f5c\u3002\n else {\n resolve(x);\n }\n } catch (e) {\n // 2.3.3.2. \u5982\u679c\u68c0\u7d22 x.then \u7684\u7ed3\u679c\u629b\u51fa\u5f02\u5e38 e\uff0c\u4f7f\u7528 e \u4f5c\u4e3a reason \u5bf9 promise \u6267\u884c reject \u64cd\u4f5c\u3002\n // 2.3.3.3.4. \u5982\u679c\u8c03\u7528 then \u65f6\u629b\u51fa\u4e00\u4e2a\u5f02\u5e38 e\uff0c\n // 2.3.3.3.4.1. \u5982\u679c resolvePromise \u6216 rejectPromise \u5df2\u7ecf\u88ab\u8c03\u7528\u8fc7\u4e86\uff0c\u5219\u5ffd\u7565\u5f02\u5e38\u3002\n if (isCalled) return;\n isCalled = true;\n // 2.3.3.3.4.2. \u5426\u5219\uff0c\u4f7f\u7528 e \u4f5c\u4e3a reason \u5bf9 promise \u6267\u884c reject \u64cd\u4f5c\u3002\n reject(e);\n }\n }\n // 2.3.4. \u5982\u679c x \u4e0d\u662f\u4e00\u4e2a\u5bf9\u8c61\u6216\u8005\u51fd\u6570\uff0c\u4f7f\u7528 x \u4f5c\u4e3a\u503c\u5bf9 promise \u6267\u884c fulfill \u64cd\u4f5c\u3002\n else {\n resolve(x);\n }\n}\n')),(0,i.kt)("h3",{id:"4-\u5b8c\u6574\u4ee3\u7801"},"4. \u5b8c\u6574\u4ee3\u7801"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-js"},'function Promise(executor) {\n this.state = "pending";\n this.onFulfilledCallback = [];\n this.onRejectedCallback = [];\n\n const self = this;\n\n function resolve(value) {\n setTimeout(function () {\n if (self.state === "pending") {\n self.state = "fulfilled";\n self.data = value;\n for (let i = 0; i < self.onFulfilledCallback.length; i++) {\n self.onFulfilledCallback[i](value);\n }\n }\n });\n }\n\n function reject(reason) {\n setTimeout(function () {\n if (self.state === "pending") {\n self.state = "rejected";\n self.data = reason;\n for (let i = 0; i < self.onRejectedCallback.length; i++) {\n self.onRejectedCallback[i](reason);\n }\n }\n });\n }\n\n try {\n executor(resolve, reject);\n } catch (reason) {\n reject(reason);\n }\n}\n\nPromise.prototype.then = function (onFulfilled, onRejected) {\n const self = this;\n\n let promise2;\n\n return (promise2 = new Promise(function (resolve, reject) {\n if (self.state === "fulfilled") {\n setTimeout(function () {\n if (typeof onFulfilled === "function") {\n try {\n const x = onFulfilled(self.data);\n\n promiseResolutionProcedure(promise2, x, resolve, reject);\n } catch (e) {\n reject(e);\n }\n } else {\n resolve(self.data);\n }\n });\n } else if (self.state === "rejected") {\n setTimeout(function () {\n if (typeof onRejected === "function") {\n try {\n const x = onRejected(self.data);\n\n promiseResolutionProcedure(promise2, x, resolve, reject);\n } catch (e) {\n reject(e);\n }\n } else {\n reject(self.data);\n }\n });\n } else if (self.state === "pending") {\n self.onFulfilledCallback.push(function (promise1Value) {\n if (typeof onFulfilled === "function") {\n try {\n const x = onFulfilled(self.data);\n\n promiseResolutionProcedure(promise2, x, resolve, reject);\n } catch (e) {\n reject(e);\n }\n } else {\n resolve(promise1Value);\n }\n });\n\n self.onRejectedCallback.push(function (promise1Reason) {\n if (typeof onRejected === "function") {\n try {\n const x = onRejected(self.data);\n\n promiseResolutionProcedure(promise2, x, resolve, reject);\n } catch (e) {\n reject(e);\n }\n } else {\n reject(promise1Reason);\n }\n });\n }\n }));\n};\n\nfunction promiseResolutionProcedure(promise2, x, resolve, reject) {\n if (promise2 === x) {\n return reject(new TypeError("Chaining cycle detected for promise"));\n }\n\n if (x instanceof Promise) {\n if (x.state === "pending") {\n x.then(function (value) {\n promiseResolutionProcedure(promise2, value, resolve, reject);\n }, reject);\n } else if (x.state === "fulfilled") {\n resolve(x.data);\n } else if (x.state === "rejected") {\n reject(x.data);\n }\n return;\n }\n\n if (x && (typeof x === "object" || typeof x === "function")) {\n let isCalled = false;\n\n try {\n let then = x.then;\n\n if (typeof then === "function") {\n then.call(\n x,\n function resolvePromise(y) {\n if (isCalled) return;\n isCalled = true;\n return promiseResolutionProcedure(promise2, y, resolve, reject);\n },\n function rejectPromise(r) {\n if (isCalled) return;\n isCalled = true;\n return reject(r);\n }\n );\n } else {\n resolve(x);\n }\n } catch (e) {\n if (isCalled) return;\n isCalled = true;\n reject(e);\n }\n } else {\n resolve(x);\n }\n}\n\nmodule.exports = Promise;\n')),(0,i.kt)("h2",{id:"\u6d4b\u8bd5\u4ee3\u7801"},"\u6d4b\u8bd5\u4ee3\u7801"),(0,i.kt)("p",null,"\u5f00\u5934\u6211\u4eec\u5c31\u8bf4\u8fc7\uff0cPromises/A+ \u89c4\u8303\u914d\u5957\u4e86\u6210\u719f\u7684",(0,i.kt)("a",{parentName:"p",href:"https://github.com/promises-aplus/promises-tests"},"\u6d4b\u8bd5\u7528\u4f8b"),"\uff0c\u6211\u4eec\u5fc5\u987b\u5168\u90e8\u901a\u8fc7\u624d\u7b97\u4ee3\u7801\u7f16\u5199\u6b63\u786e\u3002\u4e0b\u9762\u6211\u4eec\u5c31\u7528 872 \u4e2a\u5b98\u65b9\u6d4b\u8bd5\u7528\u4f8b\u6765\u6d4b\u8bd5\u4e00\u4e0b\u6211\u4eec\u7684\u5b8c\u6574\u4ee3\u7801\u662f\u5426\u7b26\u5408 Promises/A+ \u89c4\u8303\u3002"),(0,i.kt)("h3",{id:"1-\u66b4\u9732\u4e00\u4e2a\u7b80\u5355\u7684\u9002\u914d\u5668\u63a5\u53e3"},"1. \u66b4\u9732\u4e00\u4e2a\u7b80\u5355\u7684\u9002\u914d\u5668\u63a5\u53e3"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-js"},'// test.js\n\n// \u5bfc\u5165\u6211\u4eec\u5199\u597d\u7684 promise\nconst Promise = require("./promise.js");\n\n// \u6839\u636e\u5b98\u65b9\u6587\u6863\u66b4\u9732\u4e00\u4e2a deferred \u65b9\u6cd5\uff0c\u8fd4\u56de\u4e00\u4e2a\u5305\u542b promise\u3001resolve\u3001reject \u7684\u5bf9\u8c61\nPromise.deferred = function () {\n const obj = {};\n\n obj.promise = new Promise(function (resolve, reject) {\n obj.resolve = resolve;\n obj.reject = reject;\n });\n\n return obj;\n};\n\nmodule.exports = Promise;\n')),(0,i.kt)("h3",{id:"2-\u8fd0\u884c\u547d\u4ee4"},"2. \u8fd0\u884c\u547d\u4ee4"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-bash"},"$ npx promises-aplus-tests test.js\n")),(0,i.kt)("h3",{id:"3-\u6d4b\u8bd5\u7ed3\u679c"},"3. \u6d4b\u8bd5\u7ed3\u679c"),(0,i.kt)("p",null,(0,i.kt)("img",{parentName:"p",src:"https://user-images.githubusercontent.com/17525377/125480978-5e2eaa69-0be4-4f8e-a321-c8e58af6a415.png",alt:"\u6d4b\u8bd5\u7ed3\u679c"})),(0,i.kt)("p",null,"\u5b8c\u7f8e\u901a\u8fc7\uff01"),(0,i.kt)("h2",{id:"\u53c2\u8003\u8d44\u6599"},"\u53c2\u8003\u8d44\u6599"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("a",{parentName:"li",href:"https://promisesaplus.com/"},"Promises/A+")),(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("a",{parentName:"li",href:"https://github.com/promises-aplus/promises-tests"},"Promises/A+ Compliance Test Suite"))))}p.isMDXComponent=!0}}]);