Skip to content

Commit

Permalink
chore: publish v1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ambit-tsai committed Dec 24, 2020
1 parent 8d7c9c1 commit 96abd62
Show file tree
Hide file tree
Showing 9 changed files with 147 additions and 39 deletions.
72 changes: 55 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,30 @@


# Promise For ES
✨ A ES6 Promise implementation based on **ES3**, support almost all browsers at present, comply with ECMA-262 and Promises/A+, include ES2021.

✨ A ES2021 Promise implementation based on ES3 has high compatibility, and comply with ECMA-262 and Promises/A+

> The best way to learn `Promise` is to implement it.

## Feature
1. Base on ES3, almost all browsers are supported;
1. Comply with ECMA-262 and Promises/A+, pass the Promises/A+ compliance test, and other related tests;
1. Implement the new features about Promise of ES2018、ES2020、ES2021;


## Support
|Feature|Support|
|-|:-:|
|new Promise(*executor*)||
|Promise.prototype.then(*onFulfilled, onRejected*)||
|Promise.prototype.catch(*onRejected*)||
|Promise.prototype.finally(*onFinally*)||
|Promise.resolve(*value*)||
|Promise.reject(*reason*)||
|Promise.all(*iterable*)||
|Promise.race(*iterable*)||
|Promise.allSettled(*iterable*)||
|Promise.any(*iterable*)||
|Ability|Version|Support|
|-|:-:|:-:|
|**new** Promise(executor)|ES2015||
|Promise.prototype.**then**(onFulfilled, onRejected)|ES2015||
|Promise.prototype.**catch**(onRejected)|ES2015||
|Promise.prototype.**finally**(onFinally)|ES2018||
|Promise.**resolve**(value)|ES2015||
|Promise.**reject**(reason)|ES2015||
|Promise.**all**(iterable)|ES2015||
|Promise.**race**(iterable)|ES2015||
|Promise.**allSettled**(iterable)|ES2020||
|Promise.**any**(iterable)|ES2021||


## Install
Expand All @@ -40,7 +45,7 @@ npm i -S promise-for-es


## Usage
1. As po**l**yfill
1. As a po**l**yfill
```javascript
// ES Module
import 'promise-for-es/polyfill';
Expand All @@ -49,7 +54,7 @@ import 'promise-for-es/polyfill';
// CommonJS
require('promise-for-es/polyfill');
```
2. As po**n**yfill
2. As a po**n**yfill
```javascript
// ES Module
import Promise from 'promise-for-es';
Expand All @@ -60,13 +65,46 @@ const Promise = require('promise-for-es');
```


## Core logic
Using the example below:
```javascript
const executor = (resolutionFunc, rejectionFunc) => {
// business logic
};
const p1 = new Promise(executor);
p1.then(onFulfilled, onRejected);
```

### p1.then(onFulfilled, onRejected)
1. Create a new Promise object `p2` ;
1. Check the state of `p1` :
1. If "**pending**", push `onFulfilled` into the **fulfill list** of `p1`, and push `onRejected` into the **reject list**;
1. If "**fulfilled**", create a micro task with `onFulfilled`, `p2` and the **result** of `p1` ;
1. If "**rejected**", create a micro task with `onRejected`, `p2` and the **result** of `p1` ;
1. return `p2` ;

### new Promise(executor)
1. Create the resolving functions: `resolutionFunc`, `rejectionFunc` ;
2. Call `executor` with `resolutionFunc` and `rejectionFunc` as the arguments;

### resolutionFunc(value)
1. If any resolving function has been called, return;
1. If `value` is **thenable**, create a micro task with `value`, return;
1. Change the state of `p1` to "**fulfilled**";
1. Create a micro task for each element of **fulfill list**;

### rejectionFunc(reason)
1. If any resolving function has been called, return;
1. Change the state of `p1` to "**rejected**";
1. Create a micro task for each element of **reject list**;


## Test
1. `npm run test:aplus` to run Promises/A+ compliance test;
1. `npm run test:es6` to run <a href="https://github.com/promises-es6/promises-es6" target="_blank">promises-es6-tests</a>;
1. `npm run test:core-js` to run the <a href="https://github.com/zloirock/core-js/tree/master/tests/pure" target="_blank">core-js</a> tests about Promise;



## Reference
1. <a href="https://www.ecma-international.org/ecma-262/11.0/index.html#sec-promise-objects" target="_blank">ECMA-262</a>
1. <a href="https://promisesaplus.com/" target="_blank">Promises/A+</a>
82 changes: 61 additions & 21 deletions README.zh-CN.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<a href="https://promisesaplus.com/">
<a href="https://promisesaplus.com/" target="_blank">
<img
title="Promises/A+ 1.1.1 compliant"
alt="Promises/A+ logo"
Expand All @@ -12,25 +12,31 @@


# Promise For ES
✨ 基于 ES3 实现的 ES6 Promise 支持几乎所有的浏览器,遵从 ECMA-262 与 Promises/A+ 标准,包含 ES2021 特性。

✨ ES2021 Promise 的实现,使用 ES3 语法拥有超高兼容性,并遵从 ECMA-262 与 Promises/A+ 标准

> 学习 `Promise` 的最佳方式是实现它。

## 支持
|特性|支持|
|-|:-:|
|new Promise(*executor*)||
|Promise.prototype.then(*onFulfilled, onRejected*)||
|Promise.prototype.catch(*onRejected*)||
|Promise.prototype.finally(*onFinally*)||
|Promise.resolve(*value*)||
|Promise.reject(*reason*)||
|Promise.all(*iterable*)||
|Promise.race(*iterable*)||
|Promise.allSettled(*iterable*)||
|Promise.any(*iterable*)||
Almost all browsers are supported
基于 ES3 实现的 ES6 Promise 支持几乎所有的浏览器,遵从 ECMA-262 与 Promises/A+ 标准,包含 ES2021 特性。
## 特性
1. 基于 ES3,几乎所有浏览器都受支持;
1. 遵从 ECMA-262 与 Promises/A+ 标准,并通过 Promises/A+ 合规性测试,以及其它相关测试;
1. 实现 ES2018、ES2020、ES2021 中关于 Promise 的新特性;


## 支持情况
|能力|版本|支持|
|-|:-:|:-:|
|**new** Promise(executor)|ES2015||
|Promise.prototype.**then**(onFulfilled, onRejected)|ES2015||
|Promise.prototype.**catch**(onRejected)|ES2015||
|Promise.prototype.**finally**(onFinally)|ES2018||
|Promise.**resolve**(value)|ES2015||
|Promise.**reject**(reason)|ES2015||
|Promise.**all**(iterable)|ES2015||
|Promise.**race**(iterable)|ES2015||
|Promise.**allSettled**(iterable)|ES2020||
|Promise.**any**(iterable)|ES2021||


## 安装
Expand Down Expand Up @@ -60,12 +66,46 @@ const Promise = require('promise-for-es');
```


## 核心逻辑
以下面的代码为例:
```javascript
const executor = (resolutionFunc, rejectionFunc) => {
// 业务逻辑
};
const p1 = new Promise(executor);
p1.then(onFulfilled, onRejected);
```

### p1.then(onFulfilled, onRejected)
1. 创建一个新的 Promise 对象 `p2`
1. 检查 `p1` 的状态:
1. 若是 "pending",将 `onFulfilled` 添加到 `p1`**fulfill list**`onRejected` 添加到 **reject list**
1. 若是 "fulfilled",以 `onFulfilled``p2``p1` 的结果 新建一个微任务;
1. 若是 "rejected",以 `onRejected``p2``p1` 的结果 新建一个微任务;
1. 返回 `p2` ;

### new Promise(executor)
1. 创建解析函数:`resolutionFunc``rejectionFunc`
2.`resolutionFunc``rejectionFunc` 作为参数调用 `executor`;

### resolutionFunc(value)
1. 若任意解析函数已被调用,返回;
1.`value`**thenable**,以 `value` 新建一个微任务,并返回;
1. 改变 `p1` 的状态为 "**fulfilled**";
1.**fulfill list** 的每个元素新建一个微任务;

### rejectionFunc(reason)
1. 若任意解析函数已被调用,返回;
1. 改变 `p1` 的状态为 "**rejected**";
1.**reject list** 的每个元素新建一个微任务;


## 测试
1. `npm run test:aplus` 运行 Promises/A+ 合规性测试;
1. `npm run test:es6` 运行 <a href="https://github.com/promises-es6/promises-es6" target="_blank">promises-es6-tests</a>;
1. `npm run test:core-js` 运行 <a href="https://github.com/zloirock/core-js/tree/master/tests/pure" target="_blank">core-js</a> 关于 Promise 的相关测试;
1. `npm run test:aplus` 运行 Promises/A+ 合规性测试
1. `npm run test:es6` 运行 <a href="https://github.com/promises-es6/promises-es6" target="_blank">promises-es6-tests</a>
1. `npm run test:core-js` 运行 <a href="https://github.com/zloirock/core-js/tree/master/tests/pure" target="_blank">core-js</a> 关于 Promise 的相关测试


## 参考
1. <a href="https://www.ecma-international.org/ecma-262/11.0/index.html#sec-promise" target="_blank">ECMA-262</a>
1. <a href="https://www.ecma-international.org/ecma-262/11.0/index.html#sec-promise-objects" target="_blank">ECMA-262</a>
1. <a href="https://promisesaplus.com/" target="_blank">Promises/A+</a>
9 changes: 9 additions & 0 deletions dist/promise-for-es.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions dist/promise-for-es.js.map

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions dist/promise-for-es.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* promise-for-es
* @version 1.0.0
* @author Ambit tsai <ambit_tsai@qq.com>
* @license Apache-2.0
* @see {@link https://github.com/ambit-tsai/promise-for-es#readme}
*/
var e,t,n,r="object"==typeof window?window:"object"==typeof global?global:self,o=undefined;try{e=Function("iterable","callback","var i = 0;for (var element of iterable) { callback(element, i++, iterable);}")}catch(R){e=function(e,t){for(var n=0,r=e.length;n<r;++n)t(e[n],n++,e)}}function c(e){return"function"==typeof e}function i(e){return!!e&&("object"==typeof e||c(e))}function a(e){throw new TypeError(e)}function l(e){a("Promise."+e+" called on non-object")}c(r.AggregateError)?t=r.AggregateError:(t=function(e,t){this.errors=e,this.message=t}).prototype=Error.prototype;try{Object.defineProperty({},"",{}),n=function(e,t,n,r){void 0===r&&(r=!1),Object.defineProperty(e,t,{configurable:!r,value:n})}}catch(R){n=function(e,t,n){return e[t]=n}}var u,s=r.MutationObserver||r.WebKitMutationObserver;function f(e,t){var n=e.Capability,r=e.Handler;try{var o=void 0;if(r)o=r(t);else{if("Reject"===e.Type)throw t;o=t}n.Resolve(o)}catch(R){n.Reject(R)}}function v(e){var t=!1;return{resolve:function(r){if(!t){t=!0;try{if(r===e&&a("Chaining cycle detected for promise"),i(r)){var l=r.then;if(c(l))return void u(y,[e,r,l])}!function(e,t){n(e,"_state","fulfilled",!0),n(e,"_result",t,!0);var r=e._fulfillReactions;n(e,"_fulfillReactions",o,!0),n(e,"_rejectReactions",o,!0),p(r,t)}(e,r)}catch(R){h(e,R)}}},reject:function(n){t||(t=!0,h(e,n))}}}function h(e,t){n(e,"_state","rejected",!0),n(e,"_result",t,!0);var r=e._rejectReactions;n(e,"_fulfillReactions",o,!0),n(e,"_rejectReactions",o,!0),e._isHandled,p(r,t)}function p(e,t){for(var n=0,r=e;n<r.length;n++){var o=r[n];u(f,[o,t])}}function y(e,t,n){var r=v(e),o=r.resolve,c=r.reject;try{n.call(t,o,c)}catch(R){c(R)}}function d(e){c(e)&&i(e.prototype)||a("call on non-constructor");var t={};return t.Promise=new e((function(e,n){t.Resolve=e,t.Reject=n})),c(t.Resolve)&&c(t.Reject)||a("Promise resolve or reject function is not callable"),t}u=s?function(e,t){var n=new s((function(){e.apply(o,t),n.disconnect()})),r=document.createElement("a");n.observe(r,{attributes:!0}),r.setAttribute("b","")}:function(e,t){setTimeout((function(){return e.apply(o,t)}))};var j=function(){function r(e){var t=this;t instanceof r||a("call Promise constructor without 'new'"),c(e)||a("argument is not a function"),n(t,"_state","pending"),n(t,"_fulfillReactions",[]),n(t,"_rejectReactions",[]),n(t,"_result",o),n(t,"_isHandled",!1);var i=v(t),l=i.resolve,u=i.reject;try{e(l,u)}catch(R){u(R)}}return r.prototype.then=function(e,t){var i=this;i instanceof r||a("Promise.prototype.then called on incompatible object");var l=d(r),s={Capability:l,Type:"Fulfill",Handler:c(e)?e:o},v={Capability:l,Type:"Reject",Handler:c(t)?t:o};return"pending"===i._state?(i._fulfillReactions.push(s),i._rejectReactions.push(v)):"fulfilled"===i._state?u(f,[s,i._result]):(i._isHandled,u(f,[v,i._result])),n(i,"_isHandled",!0),l.Promise},r.prototype["catch"]=function(e){return this.then(o,e)},r.prototype["finally"]=function(e){var t,n,r=this;return c(e)?(t=function(t){var n=e();return r.constructor.resolve(n).then((function(){return t}))},n=function(t){var n=e();return r.constructor.resolve(n).then((function(){throw t}))}):(t=e,n=e),r.then(t,n)},r.prototype.toString=function(){return"[object Promise]"},r.prototype.toLocaleString=function(){return"[object Promise]"},r.resolve=function(e){var t=this;if(i(t)||l("resolve"),i(e)&&e instanceof t)return e;var n=d(t);return n.Resolve(e),n.Promise},r.reject=function(e){i(this)||l("reject");var t=d(this);return t.Reject(e),t.Promise},r.all=function(t){var n=this;i(n)||l("all");var r=d(n);try{var o=0,c=[];e(t,(function(e,t){o++,n.resolve(e).then((function(e){c[t]=e,--o||r.Resolve(c)}),r.Reject)})),o?c.length=o:r.Resolve(c)}catch(R){r.Reject(R)}return r.Promise},r.race=function(t){var n=this;i(n)||l("race");var r=d(n);try{e(t,(function(e){n.resolve(e).then(r.Resolve,r.Reject)}))}catch(R){r.Reject(R)}return r.Promise},r.allSettled=function(t){var n=this;i(n)||l("allSettled");var r=d(n);try{var o=0,c=[];e(t,(function(e,t){o++,n.resolve(e).then((function(e){c[t]={status:"fulfilled",value:e},--o||r.Resolve(c)}),(function(e){c[t]={status:"rejected",reason:e},--o||r.Resolve(c)}))})),o?c.length=o:r.Resolve(c)}catch(R){r.Reject(R)}return r.Promise},r.any=function(n){var r=this;i(r)||l("any");var o=d(r);try{var c=0,a=[],u="All Promises rejected";e(n,(function(e,n){c++,r.resolve(e).then(o.Resolve,(function(e){a[n]=e,--c||o.Reject(new t(a,u))}))})),c?a.length=c:o.Reject(new t(a,u))}catch(R){o.Reject(R)}return o.Promise},r}();export default j;
//# sourceMappingURL=promise-for-es.mjs.map
1 change: 1 addition & 0 deletions dist/promise-for-es.mjs.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "promise-for-es",
"version": "1.0.0",
"description": "A ES2021 Promise implementation with high compatibility, comply with ECMA-262 and Promises/A+",
"description": "A ES2021 Promise implementation based on ES3 has high compatibility, and comply with ECMA-262 and Promises/A+",
"main": "dist/promise-for-es.js",
"module": "dist/promise-for-es.mjs",
"scripts": {
Expand Down
Loading

0 comments on commit 96abd62

Please sign in to comment.