{"id":13399656,"url":"https://github.com/promises-aplus/promises-spec","last_synced_at":"2025-05-15T10:06:58.205Z","repository":{"id":5195759,"uuid":"6370862","full_name":"promises-aplus/promises-spec","owner":"promises-aplus","description":"An open standard for sound, interoperable JavaScript promises—by implementers, for implementers.","archived":false,"fork":false,"pushed_at":"2023-08-02T03:40:12.000Z","size":253,"stargazers_count":1838,"open_issues_count":47,"forks_count":164,"subscribers_count":82,"default_branch":"master","last_synced_at":"2025-04-09T03:12:07.585Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://promisesaplus.com/","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/promises-aplus.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":null,"license":"COPYING.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2012-10-24T14:06:46.000Z","updated_at":"2025-04-08T08:42:17.000Z","dependencies_parsed_at":"2022-09-11T10:41:04.550Z","dependency_job_id":"6177d761-c48a-40ec-9315-0ec024aced4e","html_url":"https://github.com/promises-aplus/promises-spec","commit_stats":{"total_commits":197,"total_committers":85,"mean_commits":"2.3176470588235296","dds":0.6903553299492386,"last_synced_commit":"939892fcda47ed6228193a8b9900eed6fd525f48"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promises-aplus%2Fpromises-spec","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promises-aplus%2Fpromises-spec/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promises-aplus%2Fpromises-spec/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/promises-aplus%2Fpromises-spec/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/promises-aplus","download_url":"https://codeload.github.com/promises-aplus/promises-spec/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254319720,"owners_count":22051073,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T19:00:40.979Z","updated_at":"2025-05-15T10:06:53.180Z","avatar_url":"https://github.com/promises-aplus.png","language":null,"funding_links":[],"categories":["Others","miscellaneous","others"],"sub_categories":[],"readme":"# Promises/A+\n\n**An open standard for sound, interoperable JavaScript promises\u0026mdash;by implementers, for implementers.**\n\nA *promise* represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its `then` method, which registers callbacks to receive either a promise's eventual value or the reason why the promise cannot be fulfilled.\n\nThis specification details the behavior of the `then` method, providing an interoperable base which all Promises/A+ conformant promise implementations can be depended on to provide. As such, the specification should be considered very stable. Although the Promises/A+ organization may occasionally revise this specification with minor backward-compatible changes to address newly-discovered corner cases, we will integrate large or backward-incompatible changes only after careful consideration, discussion, and testing.\n\nHistorically, Promises/A+ clarifies the behavioral clauses of the earlier [Promises/A proposal](http://wiki.commonjs.org/wiki/Promises/A), extending it to cover *de facto* behaviors and omitting parts that are underspecified or problematic.\n\nFinally, the core Promises/A+ specification does not deal with how to create, fulfill, or reject promises, choosing instead to focus on providing an interoperable `then` method. Future work in companion specifications may touch on these subjects.\n\n## Terminology\n\n1. \"promise\" is an object or function with a `then` method whose behavior conforms to this specification.\n1. \"thenable\" is an object or function that defines a `then` method.\n1. \"value\" is any legal JavaScript value (including `undefined`, a thenable, or a promise).\n1. \"exception\" is a value that is thrown using the `throw` statement.\n1. \"reason\" is a value that indicates why a promise was rejected.\n\n## Requirements\n\n### Promise States\n\nA promise must be in one of three states: pending, fulfilled, or rejected.\n\n1. When pending, a promise:\n    1. may transition to either the fulfilled or rejected state.\n1. When fulfilled, a promise:\n    1. must not transition to any other state.\n    1. must have a value, which must not change.\n1. When rejected, a promise:\n    1. must not transition to any other state.\n    1. must have a reason, which must not change.\n\nHere, \"must not change\" means immutable identity (i.e. `===`), but does not imply deep immutability.\n\n### The `then` Method\n\nA promise must provide a `then` method to access its current or eventual value or reason.\n\nA promise's `then` method accepts two arguments:\n\n```js\npromise.then(onFulfilled, onRejected)\n```\n\n1. Both `onFulfilled` and `onRejected` are optional arguments:\n    1. If `onFulfilled` is not a function, it must be ignored.\n    1. If `onRejected` is not a function, it must be ignored.\n1. If `onFulfilled` is a function:\n    1. it must be called after `promise` is fulfilled, with `promise`'s value as its first argument.\n    1. it must not be called before `promise` is fulfilled.\n    1. it must not be called more than once.\n1. If `onRejected` is a function,\n    1. it must be called after `promise` is rejected, with `promise`'s reason as its first argument.\n    1. it must not be called before `promise` is rejected.\n    1. it must not be called more than once.\n1. `onFulfilled` or `onRejected` must not be called until the [execution context](https://es5.github.io/#x10.3) stack contains only platform code. [[3.1](#notes)].\n1. `onFulfilled` and `onRejected` must be called as functions (i.e. with no `this` value). [[3.2](#notes)]\n1. `then` may be called multiple times on the same promise.\n    1. If/when `promise` is fulfilled, all respective `onFulfilled` callbacks must execute in the order of their originating calls to `then`.\n    1. If/when `promise` is rejected, all respective `onRejected` callbacks must execute in the order of their originating calls to `then`.\n1. `then` must return a promise [[3.3](#notes)].\n\n    ```js\n    promise2 = promise1.then(onFulfilled, onRejected);\n    ```\n\n    1. If either `onFulfilled` or `onRejected` returns a value `x`, run the Promise Resolution Procedure `[[Resolve]](promise2, x)`.\n    1. If either `onFulfilled` or `onRejected` throws an exception `e`, `promise2` must be rejected with `e` as the reason.\n    1. If `onFulfilled` is not a function and `promise1` is fulfilled, `promise2` must be fulfilled with the same value as `promise1`.\n    1. If `onRejected` is not a function and `promise1` is rejected, `promise2` must be rejected with the same reason as `promise1`.\n\n### The Promise Resolution Procedure\n\nThe **promise resolution procedure** is an abstract operation taking as input a promise and a value, which we denote as `[[Resolve]](promise, x)`. If `x` is a thenable, it attempts to make `promise` adopt the state of `x`, under the assumption that `x` behaves at least somewhat like a promise. Otherwise, it fulfills `promise` with the value `x`.\n\nThis treatment of thenables allows promise implementations to interoperate, as long as they expose a Promises/A+-compliant `then` method. It also allows Promises/A+ implementations to \"assimilate\" nonconformant implementations with reasonable `then` methods.\n\nTo run `[[Resolve]](promise, x)`, perform the following steps:\n\n1. If `promise` and `x` refer to the same object, reject `promise` with a `TypeError` as the reason.\n1. If `x` is a promise, adopt its state [[3.4](#notes)]:\n   1. If `x` is pending, `promise` must remain pending until `x` is fulfilled or rejected.\n   1. If/when `x` is fulfilled, fulfill `promise` with the same value.\n   1. If/when `x` is rejected, reject `promise` with the same reason.\n1. Otherwise, if `x` is an object or function,\n   1. Let `then` be `x.then`. [[3.5](#notes)]\n   1. If retrieving the property `x.then` results in a thrown exception `e`, reject `promise` with `e` as the reason.\n   1. If `then` is a function, call it with `x` as `this`, first argument `resolvePromise`, and second argument `rejectPromise`, where:\n      1. If/when `resolvePromise` is called with a value `y`, run `[[Resolve]](promise, y)`.\n      1. If/when `rejectPromise` is called with a reason `r`, reject `promise` with `r`.\n      1. If both `resolvePromise` and `rejectPromise` are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.\n      1. If calling `then` throws an exception `e`,\n         1. If `resolvePromise` or `rejectPromise` have been called, ignore it.\n         1. Otherwise, reject `promise` with `e` as the reason.\n   1. If `then` is not a function, fulfill `promise` with `x`.\n1. If `x` is not an object or function, fulfill `promise` with `x`.\n\nIf a promise is resolved with a thenable that participates in a circular thenable chain, such that the recursive nature of `[[Resolve]](promise, thenable)` eventually causes `[[Resolve]](promise, thenable)` to be called again, following the above algorithm will lead to infinite recursion. Implementations are encouraged, but not required, to detect such recursion and reject `promise` with an informative `TypeError` as the reason. [[3.6](#notes)]\n\n## Notes\n\n1. Here \"platform code\" means engine, environment, and promise implementation code. In practice, this requirement ensures that `onFulfilled` and `onRejected` execute asynchronously, after the event loop turn in which `then` is called, and with a fresh stack. This can be implemented with either a \"macro-task\" mechanism such as [`setTimeout`](https://html.spec.whatwg.org/multipage/webappapis.html#timers) or [`setImmediate`](https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/setImmediate/Overview.html#processingmodel), or with a \"micro-task\" mechanism such as [`MutationObserver`](https://dom.spec.whatwg.org/#interface-mutationobserver) or [`process.nextTick`](http://nodejs.org/api/process.html#process_process_nexttick_callback). Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or \"trampoline\" in which the handlers are called.\n\n1. That is, in strict mode `this` will be `undefined` inside of them; in sloppy mode, it will be the global object.\n\n1. Implementations may allow `promise2 === promise1`, provided the implementation meets all requirements. Each implementation should document whether it can produce `promise2 === promise1` and under what conditions.\n\n1. Generally, it will only be known that `x` is a true promise if it comes from the current implementation. This clause allows the use of implementation-specific means to adopt the state of known-conformant promises.\n\n1. This procedure of first storing a reference to `x.then`, then testing that reference, and then calling that reference, avoids multiple accesses to the `x.then` property. Such precautions are important for ensuring consistency in the face of an accessor property, whose value could change between retrievals.\n\n1. Implementations should *not* set arbitrary limits on the depth of thenable chains, and assume that beyond that arbitrary limit the recursion will be infinite. Only true cycles should lead to a `TypeError`; if an infinite chain of distinct thenables is encountered, recursing forever is the correct behavior.\n\n---\n\n\u003cp xmlns:dct=\"http://purl.org/dc/terms/\" xmlns:vcard=\"http://www.w3.org/2001/vcard-rdf/3.0#\"\u003e\n  \u003ca rel=\"license\"\n     href=\"https://creativecommons.org/publicdomain/zero/1.0/\"\u003e\n    \u003cimg src=\"https://i.creativecommons.org/p/zero/1.0/88x31.png\" style=\"border-style: none;\" alt=\"CC0\" /\u003e\n  \u003c/a\u003e\n  \u003cbr /\u003e\n  To the extent possible under law,\n  \u003ca rel=\"dct:publisher\"\n     href=\"https://github.com/promises-aplus\"\u003e\n    \u003cspan property=\"dct:title\"\u003ethe Promises/A+ organization\u003c/span\u003e\u003c/a\u003e\n  has waived all copyright and related or neighboring rights to\n  \u003cspan property=\"dct:title\"\u003ePromises/A+ Promise Specification\u003c/span\u003e.\nThis work is published from:\n\u003cspan property=\"vcard:Country\" datatype=\"dct:ISO3166\"\n      content=\"US\" about=\"https://github.com/promises-aplus\"\u003e\n  United States\u003c/span\u003e.\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpromises-aplus%2Fpromises-spec","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpromises-aplus%2Fpromises-spec","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpromises-aplus%2Fpromises-spec/lists"}