Skip to content

Commit

Permalink
Fixed a bug with capturing the progress of a generator with nested ch…
Browse files Browse the repository at this point in the history
…ains;

Added error code filter to the `isCanceledError` method;
  • Loading branch information
DigitalBrainJS committed May 5, 2021
1 parent 12e9411 commit 7d1b6ae
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 70 deletions.
23 changes: 15 additions & 8 deletions lib/c-promise.js
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,7 @@ const CPromise= class CPromise extends Promise {
return this;
}

[_setInnerChain](chain, captureProgress){
[_setInnerChain](chain, captureProgress= true){
const shadow= this[_shadow];

shadow.innerChain = chain;
Expand Down Expand Up @@ -742,7 +742,7 @@ const CPromise= class CPromise extends Promise {
}

if (this.constructor.isCPromise(value)) {
this[_setInnerChain](value, true);
this[_setInnerChain](value);
}

super.then.call(
Expand Down Expand Up @@ -1512,7 +1512,7 @@ const CPromise= class CPromise extends Promise {
shadow.innerChain[_events]= null;
}

scope[_setInnerChain](promise, true);
scope[_setInnerChain](promise);

return promise;
}
Expand Down Expand Up @@ -1817,6 +1817,17 @@ const CPromise= class CPromise extends Promise {
}
}

const captureProgress= ()=>{
if(promise.isCaptured) return;
promise.progress((value, scope, data) => {
setProgress(value, scope, data);
});
}

!scope.isCaptured && scope.onCapture(()=>{
promise && captureProgress();
})

const next = (r) => {
if (r.done) {
return resolve(r.value);
Expand All @@ -1829,11 +1840,7 @@ const CPromise= class CPromise extends Promise {
sum += weight;
weight = promise.isChain ? 1 : promise.weight();

setImmediate(() => {
scope[_shadow].isCaptured && promise.progress((value, scope, data) => {
setProgress(value, scope, data);
});
});
scope.isCaptured && captureProgress(promise);

return promise.then(onFulfilled, onRejected);
}
Expand Down
6 changes: 4 additions & 2 deletions lib/canceled-error.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,13 @@ const CanceledError= class CanceledError extends Error {
/**
* Check whether object is an instance of CanceledError
* @param thing
* @param {...string} [codes] codes to match
* @returns {boolean}
*/

static isCanceledError(thing) {
return thing && (thing instanceof this || isExternalCanceledError(thing) && warnVersionInteraction(thing));
static isCanceledError(thing, ...codes) {
return thing && (thing instanceof this || isExternalCanceledError(thing) && warnVersionInteraction(thing)) &&
(!codes.length || codes.some(code => code === thing.code));
}

static registerErrors(errors) {
Expand Down
6 changes: 1 addition & 5 deletions lib/validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,7 @@ validators.object = (schema, required, allowUnknown = false) => {
validators.array = (...validators) => {
const validator = validators.length > 1 ? union(...validators) : validators[0];

return compose(array, typify((thing) => {
if (thing.every(validator) === true) {
return true;
}
}, `<${renderValidator(validator)||'*'}>`))
return compose(array, typify((thing) => thing.every(validator), `<${renderValidator(validator)||'*'}>`))
}

validators.rest = (...validators) => {
Expand Down
109 changes: 67 additions & 42 deletions playground/src/TestComponent.js
Original file line number Diff line number Diff line change
@@ -1,59 +1,84 @@
import React, {Component} from "react";
import {CPromise, CanceledError, ReactComponent, E_REASON_UNMOUNTED, async, listen, cancel, progress, canceled} from "../../lib/c-promise";
import React, { Component } from "react";
import {
CPromise,
CanceledError,
ReactComponent,
E_REASON_UNMOUNTED,
listen,
async,
cancel
} from "c-promise2";
import { Spinner } from "react-bootstrap";
import cpAxios from "cp-axios";

class ProtoComponent extends Component{
onClick2(){
console.log('ProtoComponent::click2', this);
}
}

@ReactComponent
class TestComponent extends ProtoComponent{
class TestComponent extends Component {
state = {
text: ""
text: "idle",
loading: false,
loader: false
};

*componentDidMount(scope) {
console.log('mount', scope);
scope.onCancel((err)=> console.log(`Cancel: ${err}`));
yield CPromise.delay(3000);
*componentDidMount() {
console.log("mounted");
yield this.fetch();
}

onClick2(){
console.log('TestComponent::click2', this);
super.onClick2();
* fetch() {
this.setState({text: "fetching...", loading: true});
yield CPromise.race([
this.showLoader(1000, 'loader'),
CPromise.run(function* () {
try {
const response = yield cpAxios(this.props.url).timeout(
this.props.timeout
);
this.setState({
text: JSON.stringify(response.data, null, 2),
loading: false
});
} catch (err) {
CanceledError.rethrow(err, E_REASON_UNMOUNTED);
this.setState({text: err.toString(), loading: false});
}
}, {context: this})
])
}

@listen
*fetch(){
this.setState({text: "fetching..."});
try {
const response = yield cpAxios(this.props.url).timeout(this.props.timeout);
this.setState({text: JSON.stringify(response.data, null, 2)});
} catch (err) {
CanceledError.rethrow(err, E_REASON_UNMOUNTED);
this.setState({text:err.toString()});
}
@async({ scopeArg: true })
*showLoader(scope, delay= 1000, stateVar) {
yield CPromise.delay(delay);
this.setState({ [stateVar]: true });
scope.onDone(()=>{
this.setState({ [stateVar]: false });
})
scope.pause();
}

render() {
return <div className="component">
<div className="caption">useAsyncEffect demo:</div>
<div>{this.state.text}</div>
<button
className="btn btn-success"
onClick={this.fetch}
>
Fetch data
</button>
<button className="btn btn-warning" onClick={()=>cancel.call(this, 'oops!')}>
Cancel request
</button>
<button className="btn btn-info" onClick={this.onClick2}>Listener binding test</button>
</div>
return (
<div className="component">
<div className="caption">CPromise decorators demo:</div>
<div>
{this.state.loader ? (
<Spinner animation="border" variant="primary" />
) : null}
{this.state.text}
</div>
<button className="btn btn-success" onClick={() => this.fetch()}>
Fetch data
</button>
<button
className="btn btn-warning"
onClick={() => cancel.call(this, "oops!")}
>
Cancel request
</button>
</div>
);
}
}

export default TestComponent;
console.log("componentDidMount", TestComponent.prototype.componentDidMount);

export default TestComponent;
35 changes: 22 additions & 13 deletions test/tests/CPromise.js
Original file line number Diff line number Diff line change
Expand Up @@ -471,22 +471,31 @@ module.exports = {

return chain;
},
'should support progress capturing': async function () {
const expected = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1];
let index = 0;
'progress capturing': {
'should support progress capturing': async function () {
const expected = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 1];
let index = 0;

const chain = CPromise.from(function* () {
this.innerWeight(10)
let i = 10;
while (--i > 0) {
const fn= CPromise.promisify(function*(){
this.innerWeight(2);
yield CPromise.delay(100);
}
}).progress(value => {
assert.equal(value, expected[index]);
index++;
});
yield CPromise.delay(100);
})

return chain;
const chain = CPromise.from(function* () {
this.innerWeight(10);
let i = 9;
while (--i >= 0) {
yield CPromise.delay(100);
}
yield fn();
}).progress(value => {
assert.equal(value, expected[index], `${value}!=${expected[index]} progress tick value`);
index++;
});

return chain;
}
},

'should proxy signals': async function () {
Expand Down

0 comments on commit 7d1b6ae

Please sign in to comment.