add generator support
This commit is contained in:
parent
9e3b6a59cb
commit
fd83139ed5
36
README.md
36
README.md
|
@ -66,5 +66,41 @@ if (parseStatus.Of(SyntaxError)) {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Handle functions:
|
||||||
|
|
||||||
|
Grip can also handle functions:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const [result, status] = grip(() => "ok");
|
||||||
|
// result = "ok"
|
||||||
|
|
||||||
|
const [result1, status1] = grip(() => {
|
||||||
|
if (1) throw new Error("error")
|
||||||
|
});
|
||||||
|
// result1 = null
|
||||||
|
// status.Of(Error) = true
|
||||||
|
```
|
||||||
|
|
||||||
|
## Handle generators
|
||||||
|
|
||||||
|
Generators can be handled using the `Iter()` method:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const res = grip(async function* () {
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
if (i == 2) throw new Error("2");
|
||||||
|
yield i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for await (let [value, status] of res.Iter()) {
|
||||||
|
if (status.Of(Error)) {
|
||||||
|
// handle error properly
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// typeof value === "number"
|
||||||
|
console.log(value)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## License
|
## License
|
||||||
MIT
|
MIT
|
||||||
|
|
48
dist/grip.js
vendored
48
dist/grip.js
vendored
|
@ -67,13 +67,57 @@ class Result extends Array {
|
||||||
Fail() {
|
Fail() {
|
||||||
return this[1].Fail();
|
return this[1].Fail();
|
||||||
}
|
}
|
||||||
Of(impl) {
|
Of(cls) {
|
||||||
return this[1].Of(impl);
|
return this[1].Of(cls);
|
||||||
|
}
|
||||||
|
Iter() {
|
||||||
|
const value = this.value;
|
||||||
|
const that = this;
|
||||||
|
if (typeof value !== "object" && !(typeof value[Symbol.iterator] === "function" || typeof value[Symbol.asyncIterator] === "function")) {
|
||||||
|
return {
|
||||||
|
async* [Symbol.asyncIterator]() {
|
||||||
|
yield new Result(that.value, that.status);
|
||||||
|
},
|
||||||
|
*[Symbol.iterator]() {
|
||||||
|
yield new Result(that.value, that.status);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
async* [Symbol.asyncIterator]() {
|
||||||
|
yield* asyncIterator(value);
|
||||||
|
},
|
||||||
|
*[Symbol.iterator]() {
|
||||||
|
yield* iterator(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var promise = (result) => {
|
var promise = (result) => {
|
||||||
return result.then((res) => new Result(res, new Ok)).catch((err) => new Result(null, Err.fromCatch(err)));
|
return result.then((res) => new Result(res, new Ok)).catch((err) => new Result(null, Err.fromCatch(err)));
|
||||||
};
|
};
|
||||||
|
var iterator = function* (iter) {
|
||||||
|
try {
|
||||||
|
let data = iter.next();
|
||||||
|
while (!data.done) {
|
||||||
|
yield new Result(data.value, new Ok);
|
||||||
|
data = iter.next();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
yield new Result(null, Err.fromCatch(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var asyncIterator = async function* (iter) {
|
||||||
|
try {
|
||||||
|
let data = await iter.next();
|
||||||
|
while (!data.done) {
|
||||||
|
yield new Result(data.value, new Ok);
|
||||||
|
data = await iter.next();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
yield new Result(null, Err.fromCatch(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
export {
|
export {
|
||||||
grip,
|
grip,
|
||||||
Ok,
|
Ok,
|
||||||
|
|
32
grip.test.ts
32
grip.test.ts
|
@ -63,3 +63,35 @@ test("fetch json", async () => {
|
||||||
expect(jsonStatus.Of(SyntaxError)).toBe(true);
|
expect(jsonStatus.Of(SyntaxError)).toBe(true);
|
||||||
expect(json === null).toBe(true);
|
expect(json === null).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("function*", async () => {
|
||||||
|
const res = grip(function* () {
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
if (i == 2) throw new Error("2");
|
||||||
|
yield i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(res.Ok()).toBe(true);
|
||||||
|
for (let [value, status] of res.Iter()) {
|
||||||
|
if (status.Of(Error)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
expect(value).toBeTypeOf("number");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test("async function*", async () => {
|
||||||
|
const res = grip(async function* () {
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
if (i == 2) throw new Error("2");
|
||||||
|
yield i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(res.Ok()).toBe(true);
|
||||||
|
for await (let [value, status] of res.Iter()) {
|
||||||
|
if (status.Of(Error)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
expect(value).toBeTypeOf("number");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
68
grip.ts
68
grip.ts
|
@ -69,19 +69,51 @@ class Result<T> extends Array<T | Status> implements IResult<T> {
|
||||||
Fail() {
|
Fail() {
|
||||||
return (this[1] as Status).Fail();
|
return (this[1] as Status).Fail();
|
||||||
}
|
}
|
||||||
Of(impl: any) {
|
Of(cls: any) {
|
||||||
return (this[1] as Status).Of(impl);
|
return (this[1] as Status).Of(cls);
|
||||||
|
}
|
||||||
|
Iter() {
|
||||||
|
const value = this.value;
|
||||||
|
const that = this;
|
||||||
|
if (
|
||||||
|
typeof value !== "object" &&
|
||||||
|
!(
|
||||||
|
typeof (value as any)[Symbol.iterator] === "function" ||
|
||||||
|
typeof (value as any)[Symbol.asyncIterator] === "function"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
async *[Symbol.asyncIterator]() {
|
||||||
|
yield new Result(that.value, that.status) as SafeResult<T>;
|
||||||
|
},
|
||||||
|
*[Symbol.iterator]() {
|
||||||
|
yield new Result(that.value, that.status) as SafeResult<T>;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
async *[Symbol.asyncIterator]() {
|
||||||
|
yield* asyncIterator<T>(value as AsyncGenerator);
|
||||||
|
},
|
||||||
|
*[Symbol.iterator]() {
|
||||||
|
yield* iterator<T>(value as Generator);
|
||||||
|
},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Unwrap<T> =
|
type Unwrap<T> =
|
||||||
T extends Promise<infer U>
|
T extends AsyncGenerator<infer U>
|
||||||
? U
|
? U
|
||||||
: T extends (...args: any) => Promise<infer U>
|
: T extends Generator<infer U>
|
||||||
? U
|
? U
|
||||||
: T extends (...args: any) => infer U
|
: T extends Promise<infer U>
|
||||||
? U
|
? U
|
||||||
: T;
|
: T extends (...args: any) => Promise<infer U>
|
||||||
|
? U
|
||||||
|
: T extends (...args: any) => infer U
|
||||||
|
? U
|
||||||
|
: T;
|
||||||
|
|
||||||
export type SafeResult<T> =
|
export type SafeResult<T> =
|
||||||
T extends Promise<any>
|
T extends Promise<any>
|
||||||
|
@ -110,3 +142,27 @@ const promise = <T>(result: Promise<T>) => {
|
||||||
.then((res) => new Result(res, new Ok()))
|
.then((res) => new Result(res, new Ok()))
|
||||||
.catch((err) => new Result(null, Err.fromCatch(err))) as Promise<Result<T>>;
|
.catch((err) => new Result(null, Err.fromCatch(err))) as Promise<Result<T>>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const iterator = function* <T>(iter: Generator) {
|
||||||
|
try {
|
||||||
|
let data = iter.next();
|
||||||
|
while (!data.done) {
|
||||||
|
yield new Result<T>(data.value as T, new Ok()) as SafeResult<T>;
|
||||||
|
data = iter.next();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
yield new Result<T>(null as T, Err.fromCatch(e)) as SafeResult<T>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const asyncIterator = async function* <T>(iter: AsyncGenerator) {
|
||||||
|
try {
|
||||||
|
let data = await iter.next();
|
||||||
|
while (!data.done) {
|
||||||
|
yield new Result<T>(data.value as T, new Ok()) as SafeResult<T>;
|
||||||
|
data = await iter.next();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
yield new Result<T>(null as T, Err.fromCatch(e)) as SafeResult<T>;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue