-
-
Notifications
You must be signed in to change notification settings - Fork 51
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
Never rejecting promise in promise middleware #253
Comments
@strdr4605 If you have some time, I would like to know your opinion. On removing saga branch actually I will remove also promise middleware. This does not make sense anymore as because request sending logic will be in another middleware which will replace sagas, I can return promise there directly, simplifying the code. And also because saga will be removed, promisified request action will be the only way to wait for a response in the place you dispatch request action, which is often needed. Previously this could also be done with I want to remove The reason for those to exist was to avoid unhandled promise rejection warning... The problem is, if you I am thinking the best would be to always resolve promise with either What do you think? |
I like more the idea of getting the request results from the redux state and not from I don't really want to promisify every action by default. And I think that This library already enforces some constraints which are hard to understand and adopt for some people (as in the case with my team, and even I have confusion). To still solve this case where import React from 'react'
import { useResolveDispatch } from 'react-saga-requests'
export const Component = ({ state }) => {
const resolveDispatch = useResolveDispatch()
resolveDispatch(fetchBooks()).then(successOrErrorOrAbortAction => {
// do something with action
})
return (
<div>
...
</div>
) |
me to, and usually this is what I do, but sometimes it is more convenient to handle response in the place you dispatch request action, for example:
onSubmit = values => {
dispatch(doMutation(values)).then(resetForm);
} This is a very common use case especially to update some local state not kept in Redux. As a comparison, this is very easy to do with redux-thunk which returns promise, but hard or impossible with redux-saga - you would need to pass resolve/reject to saga or resetForm to call inside saga, which is terrible as you then pass ui related logic to redux layer
static fetch() {
return store.dispatch(fetchSth())
} Then they collect all components, call all static fetch methods and wrap in Promise.all
There are many more use cases like that, those are just examples.
I am thinking about doing this so you don't need to worry about it, generally promisyfying request action doesn't cause any problems, if you do The only disadvantage is this promise rejection warning... that's why I was thinking about having: const { response, error } = await dispatch(fetchSth());
// not
try {
const response = await(fetchSth());
} catch(e) {
} I just want to weight all pros and cons and decide, whether allow not to promisify all actions and whether resolve or reject errors and aborts. I favour promisyfying everything because I could remove some options from API and resolving always to avoid unhandle rejection warnings. But maybe I am missing some cons of doing so, that's why I created this topic.
Could you please give me examples? I really want this library to be easy to use and logical. It is a good time to improve things before 1.0, but I need to know what problems are. Whether this is confusing API or missing examples/docs.
Interesting idea, it could be done theoretically by wrappping I really admit this topic is a tough one and I really want to make a good call before 1.0. |
As I see usage for Never rejecting promise onSubmit = async (values) => {
const { success } = await dispatch(doMutation(values));
if (success) {
resetForm(success.data);
}
} onSubmit = async (values) => {
dispatch(doMutation(values))
.then(response => {
if (response.success) {
resetForm(response.success.data);
}
});
} instead of onSubmit = async (values) => {
try {
const response = await dispatch(doMutation(values));
resetForm(response.data);
} catch() {}
} onSubmit = async (values) => {
dispatch(doMutation(values))
.then(response => {
resetForm(response.data);
}).catch();
} So the question is: 2 of my coworkers agreed that “never rejecting promise” may make sense. |
Thx for the feedback. For now I favour never rejecting promise, because unhandled promise rejections cannot really be avoided for aborts (which is not even an error) or errors if u just handle them in other places, like by reading from state. This not only spams console, sentry if u use it, but also could exit nodejs process with ssr, I am not sure for which node version, but I read in the past that this warning will actually exit nodejs process in future nodejs version. Anyway, assuming we will go this way, I would actually flatten this a little, so:
So as you see, no response but data directly, which thogether with error will resemble useQuery hook, which is good I think. Also, in all cases I would pass action key with response action (no matter what type) if someone needs it. One could even access request action as action.meta.requestAction. Also, in theory I could make it customizable, but really I dont want to do it as I want to keep API to the minimum, which also avoids confusion. One could always add own middleware to listen for promises which could once again reject them for abort and error responses. |
So interface will look like: interface PromiseAction<DataType = any> {
data: null | DataType[] | DataType;
error: null | Error;
aborted: boolean;
action: SuccessAction | ErrorAction | AbortAction;
} and const successResult = await dispatch(fetchSth());
// { data: {}, error: null, aborted: false, action: {}}
const errorResult = await dispatch(fetchSth());
// { data: null, error: Error, aborted: false, action: {}}
const abortResult = await dispatch(fetchSth());
// { data: null, error: null, aborted: true, action: {}} I would also suggest changing |
Yeah, that would be it, just I think that data would be
Thx |
I added array because of https://github.com/klis87/redux-saga-requests#getquery:
|
Good eye, and actually in previous version it might be like that. But in current version |
So const response = await dispatch(fetchSth()); will have data that comes from the server and NOT data that comes from the server AND was processed with |
@strdr4605 both, the procedure is this:
and only that processed data is then passed to reducer and returned from promise dispatch also, if you have ssr response or cached response, those 2-4 of course are not done, as it was already done for initial request. This is because caching works like that, if you fire request and sth is cached, then instead of making request it just gets state from reducer and returns that, but that was already processed with getData etc so it won't be again |
Done in |
Just an idea, maybe promise could be always resolved, but with an object with one of the following params:
success
,error
,abort
Why? Because otherwise there are issues with requests aborts which will raise unhandling promise rejection error. The same goes for error, sometimes you don't want to handle an error in a specific place because there aren't any predictable error and random network errors you wanna handle globally.
After this, we could give up
meta.asPromise
as well asauto
config in promise middleware . We could promisify all requests simply because there would be no negative side of doing so, it would reduce the boilerplace.Connected with #93 , #128 , #179 , @nemosupremo , @mowbell, @megawac , what do you think?
The text was updated successfully, but these errors were encountered: