-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
allow the filter function to be async #41
Conversation
src/test/tests.ts
Outdated
const query = `subscription Filter2($filterBoolean: Boolean){ | ||
testFilter(filterBoolean: $filterBoolean) | ||
}`; | ||
const callback = function(err, payload){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are ignoring err
, is this intended?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the test case is structured an err would be unexpected but easy enough to check.
src/test/tests.ts
Outdated
@@ -234,6 +241,31 @@ describe('SubscriptionManager', function() { | |||
}); | |||
}); | |||
|
|||
it('can use an async filter function', function(done) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i might be missing something, how do you test async here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The publish below is for Filter2
which as defined above uses setTimeout
to delay returning the result.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah i've seen it, but it means the test is actually making sure promises work,
and not that things are running in parallel..
name is abit confusing.. 🗡
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see it as that. If you revert the changes to pubsub.ts
this test will fail since and async filter is always truthy even if it ultimately returns a false value. If you have a suggestion about how to restructure the test please let me know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh no, i don't mind at all that this is what you are testing.
i would just rename the test abit to something like "can use promise inside filter function"
or something like that.. since usually when testing 'async', the testing is about being run in parallel
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the test name.
src/pubsub.ts
Outdated
} | ||
contextPromise.then((context) => { | ||
if (!filter(rootValue, context)) { | ||
Promise.resolve().then(() => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can optimize this code and do a better use of Promise chaining - this way you can avoid the inner promises and the empty resolve()
. you can also merge the two catch
that does the same thing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wasn't able to see an easy way to do that since the context needs to be in the closure for two unrelated calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NeoPhi, I see, but you think that something like this won't do the trick?
const onMessage = (rootValue) => {
const contextResult = typeof options.context === 'function' ? options.context() : context;
return Promise
.resolve(contextResult)
.then(context => { filterResult: filter(rootValue, context), context: context} )
.then(prev=> {
const {filterResult, context} = prev;
if (!filterResult) return;
return execute(
this.schema,
parsedQuery,
rootValue,
context,
options.variables,
options.operationName
);
})
.then(executionResult => {
options.callback(null, executionResult);
})
.catch((error) => {
options.callback(error);
});
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If filter
returns a Promise it will not be resolved.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@NeoPhi , so we can resolve it any way, and do the same for context, and then use Promise.all
... something like that:
const onMessage = (rootValue) => {
const contextResult = typeof options.context === 'function' ? options.context() : context;
return Promise
.resolve(contextResult)
.then(context => Promise.all([ Promise.resolve(filter(rootValue, context)), Promise.resolve(context) ]) )
.then(promisesResults=> {
const filterResult = promisesResults[0];
const context = promisesResults[1];
if (!filterResult) return;
return execute(
this.schema,
parsedQuery,
rootValue,
context,
options.variables,
options.operationName
);
})
.then(executionResult => {
options.callback(null, executionResult);
})
.catch((error) => {
options.callback(error);
});
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Woke up with the same thought. Although you can't unnest the executionResult
otherwise the callback will be called with (null, undefined)
unless that is desired.
thank you @NeoPhi ! |
@helfer This was the changed I mentioned to allow the filter function to be async.