Skip to content

Commit

Permalink
Added o-promise state property
Browse files Browse the repository at this point in the history
Fixed call `executer` after promise resolving
  • Loading branch information
RubaXa committed Jan 9, 2023
1 parent 8334083 commit 45e5cee
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 20 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@
-------------------------------
<a name="start"></a>

### v1.1.0

- Added o-promise `state` property
- Fixed call `executer` after promise resolving

---

### v1.0.0

- Base API ;]
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Open Promise 👐
---------------
Micro tool for creating Promise like Deferred
Micro tool for creating Promise likes Deferred.

```sh
npm i --save o-promise
Expand All @@ -19,9 +19,24 @@ const [promise, resolve, reject] = createOpenPromise<string>();
// 2. Deferred
const {promise, resolve, reject} = createOpenPromise<number>();

// 3. With executer
const open = createOpenPromise<boolean>((resolve, reject) => {
// 3. With executer + return
const open = createOpenPromise(() => {
return '...';
});
open.reject('aborted'); // `executer` — won't be called

// 4. With executer + promise
const open = createOpenPromise(() => {
// for example
return fetch('...');
});

// 5. With executer + resolvers
const open = createOpenPromise((resolve, reject) => {
// Your Logic
});
open.reject('aborted');
```
```

---

### 100% covergae ;]
3 changes: 2 additions & 1 deletion index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export {createOpenPromise} from './src/open/promise'
export type {OpenPromise} from './src/open/promise';
export {createOpenPromise} from './src/open/promise';
3 changes: 1 addition & 2 deletions jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
export default {
preset: "ts-jest",
testMatch: [
"**/__tests__/**/*.[jt]s?(x)",
"**/?(*.)+(spec|tests).[tj]s?(x)"
"**/?(*.)+(spec|tests).[t]s?(x)"
],
};
2 changes: 1 addition & 1 deletion package-lock.json

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

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "o-promise",
"version": "1.0.0",
"description": "Open Promise — Micro tool for creating Promise like Deferred",
"version": "1.1.0",
"description": "Open Promise — Micro tool for creating Promise likes Deferred",
"repository": {
"type": "git",
"url": "git@github.com:RubaXa/open-promise.git"
Expand Down
8 changes: 7 additions & 1 deletion src/open/promise.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ describe('api', () => {
expect(typeof open.resolve).toBe('function')
expect(typeof open.reject).toBe('function');

expect(open.state).toBe('pending');
expect(open.promise).toBe(open[0]);
expect(open.resolve).toBe(open[1]);
expect(open.reject).toBe(open[2]);
Expand All @@ -60,6 +61,7 @@ describe('api', () => {
open.reject('qux');

await expect(open.promise).resolves.toBe('foo');
expect(open.state).toBe('fulfilled');
});

it('reject', async () => {
Expand All @@ -70,6 +72,7 @@ describe('api', () => {
open.resolve('foo');

await expect(open.promise).rejects.toBe('qux');
expect(open.state).toBe('rejected');
});

describe('executer', () => {
Expand Down Expand Up @@ -106,9 +109,12 @@ describe('api', () => {
});

it('resolve before executer', async () => {
const open = createOpenPromise(() => 'fail');
const executer = jest.fn(() => 'fail');
const open = createOpenPromise(executer);

open.resolve('ok');
await expect(open.promise).resolves.toBe('ok');
expect(executer.mock.calls.length).toBe(0);
});
});
});
32 changes: 24 additions & 8 deletions src/open/promise.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
const STATE_PENDING = 'pending';

/** OpenPromise Object */
export type OpenPromiseLike<T> = [
export type OpenPromise<T> = [
Promise<T>,
(value: T) => void,
(reason: unknown) => void
(reason: unknown) => void,
] & {
state: 'pending' | 'fulfilled' | 'rejected';
promise: Promise<T>;
resolve: (value: T) => void;
reject: (reason: unknown) => void;
Expand All @@ -15,17 +18,30 @@ export const createOpenPromise = <T>(
resolve: (value: Awaited<T>) => void,
reject: (reason: unknown) => void,
) => T,
): OpenPromiseLike<Awaited<T>> => {
const d = [] as unknown as OpenPromiseLike<Awaited<T>>;
): OpenPromise<Awaited<T>> => {
const d = [] as unknown as OpenPromise<Awaited<T>>;

d.state = STATE_PENDING;

d[0] = d.promise = new Promise<any>((resolve, reject) => {
d[1] = d.resolve = resolve;
d[2] = d.reject = reject;
d[0] = d.promise = new Promise((originalResolve, originalReject) => {
const resolve = d[1] = d.resolve = (value) => {
if (d.state !== STATE_PENDING) return;
d.state = 'fulfilled';
originalResolve(value);
};

const reject = d[2] = d.reject = (reason) => {
if (d.state !== STATE_PENDING) return;
d.state = 'rejected';
originalReject(reason);
};

if (executer) {
Promise.resolve().then(() => {
if (d.state !== STATE_PENDING) return;

try {
resolve(executer(resolve, reject));
resolve(executer(resolve, reject) as Awaited<T>);
} catch (reason) {
reject(reason);
}
Expand Down

0 comments on commit 45e5cee

Please sign in to comment.