çºè¡ã©ãã«
質å
ç§ãéæããããšããŠããæ£ç¢ºãªã·ããªãªã¯ããã«èšèŒãããŠããŸãïŒ
https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-error#retrying -failed-requests
operation.setContext({
headers: {
...oldHeaders,
authorization: getNewToken(),
},
});
ãã ããããŒã¯ã³ã®æå¹æéãåããŠããå Žåã¯ã getNewToken
ãæå¹ãªèªèšŒããŒã¯ã³ãè¿ãåã«ãéåæresfreshToken
ãåŒã³åºããŠãåŸ
æ©ãããå¿
èŠããããŸãã ç§ãæãã«ã
ç§ã®è³ªåã¯ãéåæresfreshToken
åŒã³åºããè¡ãæ¹æ³ã§ãã await refreshToken()
ïŒå®äºæã«promiseã解決ããŸãïŒãè©ŠããŸãããããã°ã«èšé²ãããã¹ã¿ãã¯ãã¬ãŒã¹ãããããã¯RxJSãããªãæ··ä¹±ãããŠããããã§ãã ç§ã¯RxJSn00bã§ããã©ããªå©ãã§ã倧æè¿ã§ãïŒ
çŽæã«ç²ŸéããŠããå Žåã¯ã fromPromise
ãã«ããŒã䜿çšã§ããŸã
import { fromPromise } from 'apollo-link';
return fromPromise(refreshToken().then(token => {
operation.setContext({
headers: {
...oldHeaders,
authorization: token,
},
});
return forward(operation);
}))
@thymikeeãœãªã¥ãŒã·ã§ã³ãè©ŠããŸãããã次ã®ã¡ãã»ãŒãžã§å€±æããŸãã
Uncaught (in promise) Error: Network error: Error writing result to store for query:
query UserProfile($id: ID!) {
UserProfile(id: $id) {
id
email
first_name
last_name
activated
created_at
updated_at
last_active
roles {
id
name
__typename
}
permissions {
name
value
__typename
}
profile {
address
secondary_email
phone {
id
number
type {
id
name
__typename
}
__typename
}
__typename
}
__typename
}
}
Cannot read property 'UserProfile' of undefined
at new ApolloError (ApolloError.js:43)
at QueryManager.js:327
at QueryManager.js:759
at Array.forEach (<anonymous>)
at QueryManager.js:758
at Map.forEach (<anonymous>)
at QueryManager.webpackJsonp../node_modules/apollo-client/core/QueryManager.js.QueryManager.broadcastQueries (QueryManager.js:751)
at QueryManager.js:254
ããã«è©³ãã調ã¹ããšãäžèšã®ã³ãŒãã䜿çšãããšãApolloãªã³ã¯ã®onError
ã2ååŒã³åºãããããšãããããŸãã refresh token
çŽæãäžåºŠå®è¡ããããã«å¶éããŠãããšã©ãŒã¯ä¿®æ£ãããŸããã
äœãèµ·ãããïŒ
1ïŒåæã¯ãšãªãå®è¡ãããŸã
2ïŒå€±æããapolloã®ãªã³ã¯ãå®è¡ããŸãonError
3ïŒ?? apolloã®ãªã³ã¯onError
å床å®è¡ããŸã
4ïŒ onError
ããŒã¯ã³ãæŽæ°ããããšãçŽæããå®è¡ãçµäºããŠè§£æ±ºããŸãã
5ïŒïŒPromiseãæåããåŸãæåã®ã¯ãšãªã¯2åå®è¡ãããŸããïŒ
6ïŒæåã®ã¯ãšãªã¯ãæªå®çŸ©ãšããŠdata
ãå«ãçµæãè¿ããŸã
ããã¯ã誰ããããã«å¯Ÿãã解決çãèŠã€ããããšãæåŸ ããããã§ããããã§ãªãå Žåã¯ãæå¹æéãåãããšãã«æŽæ°ããã®ã§ã¯ãªããé·æéæå¹ãªã¢ã¯ã»ã¹ããŒã¯ã³ã®äœ¿çšã«æ»ãå¿ èŠããããŸãã
ããŒã¯ã³ååŸããžãã¯ãæ£ããå Žåã onError
ã¯1åã ãåŒã³åºãå¿
èŠããããŸãã ããŒã¯ã³ã¯ãšãªã«åé¡ãããããã§ã
@thymikeeãããŒã®promiseã䜿çšããŠéåæãªã¯ãšã¹ããåãæ¿ããŸããã ããã§ãäžèšã®ã¡ãã»ãŒãžã§å€±æããæåã®ã¯ãšãªã¯2åå®è¡ãããŸããã ãã¹ãŠã®ããŒã¯ã³ã¯ãã¹ãæã«æå¹ã§ãã
ã³ãŒãïŒ
return fromPromise(
new Promise((resolve) => {
let headers = {
//readd old headers
...operation.getContext().headers,
//switch out old access token for new one
authorization: `Bearer mynewaccesstoken`,
};
operation.setContext({
headers
});
return resolve(forward(operation));
})
)
ç·šéïŒ fromPromise
ãåé€ããæ£ããæ©èœããŸãã ã©ããããããããªã³ã¯ã¹ã¿ãã¯ã®åŠçã¯çµæãè¿ãåã«çµäºããããã forward(operation)
ã¯å®è¡ãããŸããã
fromPromise
ã³ãŒããšã³ãããïŒ172ãåæããåŸã fromPromise
ã¯ãApolloLinkãªããžã§ã¯ããæšæž¬ããŠã®ã¿äœ¿çšã§ããŸãã
解決çãç 究ããŠãããšãç§ã¯ã€ãã«ãã®ãããžã§ã¯ãã«åºããããŸããïŒ apollo-link-token-refresh
ç§ã®ã¢ãããªã³ã¯ã¹ã¿ãã¯ã¯æ¬¡ã®ããã«ãªããŸããã
[
refreshTokenLink,
requestLink,
batchHttpLink
]
refreshTokenLink
ã¯ãgraphqlãšã³ããã€ã³ããžã®å¿çãå®è¡ããåã«ãã¢ã¯ã»ã¹ããŒã¯ã³ããã§ãã¯ããããã«åžžã«åŒã³åºããããã£ãŒã ã®ããã«æ©èœããŸãã
æ®å¿µãªãããããã¯ãgraphqlãšã³ããã€ã³ããžã®åŒã³åºããåžžã«èªèšŒãããŠããå¿ èŠãããããšãåæãšããŠããŸãïŒç§ã®å Žåã¯èªèšŒãããŠããŸãïŒã
onError
ã³ãŒã«ããã¯ãaync
é¢æ°ãåãå
¥ããªããã Promise
ãè¿ãããããã§ãã ã³ãŒãhttps://github.com/apollographql/apollo-link/blob/59abe7064004b600c848ee7c7e4a97acf5d230c2/packages/apollo-link-error/src/index.ts#L60-L74ãåç
§ããŠ
ãã®åé¡ã¯ä»¥åã«å ±åãããŸããïŒïŒ190
apollo-link-retry
ãããã§è¡ãã®ãšåæ§ã«ã apollo-link-error
ãPromise
ãåŠçã§ããã°ãããããŸããããšæããŸãïŒïŒ436
åãåé¡ããããreact nativeã§apolloã䜿çšãããšãAsyncStorage onErrorããããŒã¯ã³ãåé€ããå¿ èŠããããããéåæé¢æ°ã§ããå¿ èŠããããŸã
ãã®ãœãªã¥ãŒã·ã§ã³ã¯ç§ã®ããã«åããïŒ https ïŒ
ãŠãŒãã£ãªãã£promiseToObservable.js
äœæããŠããã解決ããŸããïŒ
import { Observable } from 'apollo-link';
export default promise =>
new Observable((subscriber) => {
promise.then(
(value) => {
if (subscriber.closed) return;
subscriber.next(value);
subscriber.complete();
},
err => subscriber.error(err)
);
return subscriber; // this line can removed, as per next comment
});
ãã®åŸ
import { onError } from 'apollo-link-error';
import promiseToObservable from './promiseToObservable';
export default (refreshToken: Function) =>
onError(({
forward,
graphQLErrors,
networkError = {},
operation,
// response,
}) => {
if (networkError.message === 'UNAUTHORIZED') { // or whatever you want to check
// note: await refreshToken, then call its link middleware again!
return promiseToObservable(refreshToken()).flatMap(() => forward(operation));
}
});
@ crazy4groovyããªãã®äŸã«æè¬ããŸããããã¯æ¬åœã«åœ¹ã«ç«ã¡ãŸãã ãã ããããã«ã¯å°ããªåé¡ããããŸãã subscriber
ã¯ã Observable
æå®ã«ãããšãç¡å¹ãªæ»ãå€ã§ãããããZenObservable.SubscriptionObserver
ãŸãã
export declare type Subscriber<T> = ZenObservable.Subscriber<T>;
export declare const Observable: {
new <T>(subscriber: Subscriber<T>): Observable<T>;
};
export declare namespace ZenObservable {
interface SubscriptionObserver<T> {
closed: boolean;
next(value: T): void;
error(errorValue: any): void;
complete(): void;
}
type Subscriber<T> = (observer: SubscriptionObserver<T>) => void | (() => void) | Subscription;
}
ã€ãŸãã代ããã«undefinedãè¿ãã®ãå®å šã§ãã ãããžã§ã¯ãã®READMEãã¡ã€ã«ã«èšèŒããå¿ èŠããããšæããŸãã
UPDïŒããã«é¢ããPRãè¿œå ããŸããïŒ https ïŒ
ãã®åé¡ã¯Googleã§äžäœã«ã©ã³ã¯ãããŠããã®ã§ãããã§è§£æ±ºçãå ±æããŠãäžéšã®äººã ãæ¯æŽããŸãïŒ //gist.github.com/alfonmga/9602085094651c03cd2e270da9b2e3f7
ç§ã¯ããªãã®è§£æ±ºçãè©ŠããŸããããæ°ããåé¡ã«çŽé¢ããŠããŸãïŒ
Argument of type '(this: Observable<{}>, observer: Subscriber<{}>) => Observable<{}> | Promise<{}>' is not assignable to parameter of type '(this: Observable<{}>, subscriber: Subscriber<{}>) => TeardownLogic'.
Type 'Observable<{}> | Promise<{}>' is not assignable to type 'TeardownLogic'.
Type 'Observable<{}>' is not assignable to type 'TeardownLogic'.
Property 'unsubscribe' is missing in type 'Observable<{}>' but required in type 'Unsubscribable'
æŽæ°ãããåŸãæ°ããèªèšŒããŒã¯ã³ãã©ã®ããã«ä¿åããŸããïŒ
ãã¡ãããåè©Šè¡ãªã¯ãšã¹ãã«æ°ããããããŒãèšå®ããããšã¯ã§ããŸãããå ã®ã¢ã¯ã»ã¹ããŒã¯ã³ïŒCookieã«ä¿åããŠããïŒã¯æŽæ°ãããŸãããã€ãŸãããµãŒããŒãžã®ãã¹ãŠã®ãªã¯ãšã¹ãã§å€ãã¢ã¯ã»ã¹ããŒã¯ã³ã䜿çšãããŸãïŒãã®åŸãããäžåºŠæŽæ°ããå¿ èŠããããŸãïŒã
äœããã®çç±ã§ãæŽæ°äžã«CookieãæŽæ°ããããšãããšã次ã®ãšã©ãŒã¡ãã»ãŒãžã衚瀺ãããŸãïŒããã§æ°ããåé¡ãäœæããŸããïŒã
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at setCookie (/root/SimplyTidyAdmin/node_modules/nookies/dist/index.js:98:17)
at /root/SimplyTidyAdmin/.next/server/static/CAhshxrRWHVF6Gzbce~pU/pages/_app.js:1273:63
at process._tickCallback (internal/process/next_tick.js:68:7)
@StupidSexyJakeå€åããã¯ããªããå©ããã§ãããhttps://stackoverflow.com/questions/55356736/change-apollo-client-options-for-jwt-tokenããŒã¯ã³ãæŽæ°ããæ¹æ³ã«ã€ããŠåæ§ã®åé¡ã«ééããŸãã
ããã«ã¡ã¯ã@ crazy4groovyã«æè¬ããŸãã ç§ã¯ããªãã®è§£æ±ºçãè©ŠããŸãããããŸã åé¡ããããŸããæ°ããããŒã¯ã³ããªã¯ãšã¹ãã«èšå®ãããåã«ãgraphqlãªã¯ãšã¹ãã«ããŒã¯ã³ãè¿œå ããããã«ãŠã§ã¢ãåŒã³åºãããŸãã ãããã£ãŠãããããŒã«ã¯ãŸã ç¡å¹ãªããŒã¯ã³ããããŸãã
å°ãèæ¯æ å ±ïŒããŒã¯ã³ãç¡å¹ãªå Žåããããã¯ãŒã¯ãšã©ãŒãçºçããæŽæ°ããŒã¯ã³ãä»ããŠãæ°ããããŒã¯ã³ãååŸããŠåè©Šè¡ã§ããŸãã ãã ããæŽæ°ããŒã¯ã³ãåéãããŠããŒã«ã«ã¹ãã¬ãŒãžã«èšå®ãããåã«ããã«ãŠã§ã¢ãåŒã³åºããããããããã«ãŠã§ã¢ã«ã¯ãŸã ç¡å¹ãªããŒã¯ã³ããããŸãã æåŸã«æ°ããããŒã¯ã³ã»ãããååŸãããããããŒã¯ã³ã®æŽæ°ããžãã¯ã¯æ£åžžã«æ©èœããŸãã åé¡ãå°ããããã°ããŸãããã¿ã€ãã³ã°ã¯æ¬¡ã®ãšããã§ãã
onError
ã§ã promiseToObservable
ããžãã¯ãä»ããŠåŠçãããåè©Šè¡ãããŸããonRefreshToken
çŽæã§ããŒã¯ã³ã®ååŸãå®äºãããŸã§ãããã«ãŠã§ã¢ã¯ãã§ã«å€ãããŒã¯ã³ã§2åç®ã®å®è¡ã«ãªã£ãŠããŸãããããã®éšåã®ã¹ããããã¯æ¬¡ã®ãšããã§ãïŒonRefreshtokenãã¹ãããããŸããããã¯éåæé¢æ°ã§ãããPromiseãè¿ããŸãïŒã
const promiseToObservable = (promise: Promise<any>) =>
new Observable((subscriber: any) => {
promise.then(
value => {
console.log(subscriber);
if (subscriber.closed) return;
subscriber.next(value);
subscriber.complete();
},
err => subscriber.error(err)
);
});
const authMiddleware = setContext((operation: GraphQLRequest) => {
const token = localStorage.getItem('ca_token');
return {
headers: {
...(token && !isSkipHeader(operation)
? { authorization: `Bearer ${token}` }
: {})
}
};
});
const errorLink = onError(
({
networkError,
graphQLErrors,
operation,
forward
}: ErrorResponse): any => {
if (networkError) {
switch (networkError.statusCode) {
case 401:
console.warn('Refreshing token and trying again');
// await refreshToken, then call its link middleware again
return promiseToObservable(onRefreshToken(client.mutate)).flatMap(() => forward(operation));
default:
// Handle all other errors here. Irrelevant here.
}
}
if (graphQLErrors) {
// Handle gql errors, irrelevant here.
}
}
);
ããã§æ¬ ããŠãããã®ãæããŠãã ããã ãããããé¡ãããŸã...
OKãæ··ä¹±ãããã°ããããªãã...
ç§ã¯çããèŠã€ããŸããããããŠããã¯äœæéããããæ¢ããŠãããŠ-ãã¡ãã-ããã«æçš¿ããåŸã«èŠã€ããåŸã®æããªãã®ã§ãïŒã¢ããã¯ã©ã€ã¢ã³ãã®åæåäžã«ãç§ã¯ããã«ãŠã§ã¢ãšãšã©ãŒãªã³ã¯ã亀æããŸããã ä»ã§ã¯åäœããŸãã æããã«ããšã©ãŒãªã³ã¯ãæåã§ããå¿
èŠããããŸãã
å€ãïŒ link: from([authMiddleware, errorLink, /* others */])
æ°èŠïŒ link: from([errorLink, authMiddleware, /* others */])
ãŸããã¿ãŸãã..
ããã«ã¡ã¯ã¿ããªã
æŽæ°ããŒã¯ã³ã«onErrorã䜿çšãããšã次ã®åé¡ãçºçããŸãã nextjsã䜿çšããSSRã®ç®çã§ããã¹ãŠã®graphqlã¯ãšãªããããŒã¿ãåéããŠããŸãããããšãã°2ã€ã®ã¯ãšãªããããjwtããŒã¯ã³ã®æå¹æéãåããŠãããããããããããšã©ãŒã«ãªããšã©ããªããŸããã 次ã«ãonErrorã2åèµ·åããé«äŸ¡ãªæŽæ°ããŒã¯ã³ã2ååŒã³åºããŸãã åé¡ãã©ãããæ¥ãŠããã®ãããããŸããã ãããç§ã䜿çšããŠããã³ãŒãã§ãã ãããæäŒã£ãŠãããŸãããã
https://gist.github.com/shaxaaa/15817f1bcc7b479f3c541383d2e83650
ç§ã¯ãã®åé¡ã«å°ãåãçµã¿ãŸããããããããæ©èœããããã«ãªããŸããã ç§ã¯äžç·ã«ããã±ãŒãžãæããŸããã
https://github.com/baleeds/apollo-link-refresh-token
ãã®ããã±ãŒãžãšapollo-link-token-refreshãšåŒã°ããããã±ãŒãžã®äž»ãªéãã¯ããã®ããã±ãŒãžã¯ãããã¯ãŒã¯ãšã©ãŒãåŸ ã£ãŠããæŽæ°ãè©Šã¿ãããšã§ãã
å€æŽã®ã¢ã€ãã¢ãããã°æããŠãã ããã
åºæ¬çãªäœ¿çšæ³ã¯æ¬¡ã®ãšããã§ãã
const refreshTokenLink = getRefreshTokenLink({
authorizationHeaderKey: 'Authorization',
fetchNewAccessToken,
getAccessToken: () => localStorage.getItem('access_token'),
getRefreshToken: () => localStorage.getItem('refresh_token'),
isAccessTokenValid: accessToken => isTokenValid(accessToken),
isUnauthenticatedError: graphQLError => {
const { extensions } = graphQLError;
if (
extensions &&
extensions.code &&
extensions.code === 'UNAUTHENTICATED'
) {
return true;
}
return false;
},
});
ãŠãŒãã£ãªãã£
promiseToObservable.js
äœæããŠããã解決ããŸããïŒimport { Observable } from 'apollo-link'; export default promise => new Observable((subscriber) => { promise.then( (value) => { if (subscriber.closed) return; subscriber.next(value); subscriber.complete(); }, err => subscriber.error(err) ); return subscriber; // this line can removed, as per next comment });
ãã®åŸ
import { onError } from 'apollo-link-error'; import promiseToObservable from './promiseToObservable'; export default (refreshToken: Function) => onError(({ forward, graphQLErrors, networkError = {}, operation, // response, }) => { if (networkError.message === 'UNAUTHORIZED') { // or whatever you want to check // note: await refreshToken, then call its link middleware again! return promiseToObservable(refreshToken()).flatMap(() => forward(operation)); } });
ç§ã¯ããã䜿çšããŸããããããŒã¯ã³ã®æŽæ°èŠæ±åŸã«ãŸã å€ãããŒã¯ã³ã䜿çšããŠããããšãããããŸããã ã ãããç§ã¯æ¬¡ã®ããã«ããããšããŸãïŒ
return promiseToObservable(refreshToken()).flatMap((value) => {
operation.setContext(({ headers = {} }) => ({
headers: {
// re-add old headers
// ...headers,
Authorization: `JWT ${value.token}`
}
}));
return forward(operation)
});
ãããŠããã¯åäœããŸãã
ãã ãã ...headers
è¿œå ãããšïŒå€ãããããŒãå床远å ããããšãæå³ããŸãïŒã転éèŠæ±ãéä¿¡ãããåã«äœãåé¡ããããšããåé¡ããŸã ãããŸãã
ERROR Error: Network error: Cannot read property 'length' of null
...ããããŒã®æ¿èªãæ°ããæ¿èªãšç«¶åããå¯èœæ§ããããšæããŸãã
äžèšã®åé¡ã¯apollo-angular "apollo-angular-link-http": "^1.6.0",
ã«ãããapollo-client "apollo-link-http": "^1.5.16",
"apollo-angular-link-http": "^1.6.0",
ãããŸããããlink-errorã¯åã"apollo-link-error": "^1.1.12",
å¥ã®æ§æïŒeyesïŒ
import Vue from 'vue'
import { Observable } from 'apollo-link'
import { onError } from 'apollo-link-error'
const onGraphqlError = async ({ graphQLErrors = [], observer, operation, forward }) => {
// here you could call the refresh query in case you receive an expired error
for (let error of graphQLErrors)
observer.next(forward(operation)) // this line would retry the operation
}
const onNetworkError = async ({ observer, networkError, operation, forward }) => { }
export const errorHandler = opt => new Observable(async observer => {
try {
const payload = { ...opt, observer }
await Promise.all([onGraphqlError(payload), onNetworkError(payload)])
if (observer.closed) return
observer.complete()
} catch (error) {
observer.error(error)
}
})
ããã«ã¡ã¯ïŒ ãã«WebSocketãã©ã³ã¹ããŒãã䜿çšããŠããã®ã§ãããŒã¯ã³ã¯ãšãªããªã¯ãšã¹ãããå¿
èŠããããŸãã ãããè¡ãæ¹æ³ãããããŸããã
accessToken
æå¹æéãåãããšãµãŒããŒãå¿çãããšãã«ãåä¿¡èŠæ±ãå®è¡ããããšæããŸãã
import { onError } from "apollo-link-error";
import gql from 'graphql-tag'
// Client: VUE APOLLO
const q = {
query: gql`query token { token { accessToken } }`,
manual: true,
result({ data, loading }) {
if (!loading) {
console.log(data)
}
},
}
const link = onError(({ graphQLErrors, networkError, operation, response, forward }) => {
if (networkError) {
switch (networkError.message) {
case 'accessTokenExpired':
console.log('accessTokenExpired')
return forward(q) // NOT WORKS, NEED HELP
case 'unauthorized':
return console.log('unauthorized')
default:
return forward(operation)
}
}
return forward(operation)
})
export default link
@nikitamarciusäžèšã®åé¿çãæçš¿ããŸããããªãã¶ãŒããã«ãèŠãŠãã ãã
ããŒã¯ã³ãæŽæ°ã§ããŸãããå®éã®äŸã誰ããæäŸã§ããŸãã
@ Ramyapriya24ã¯ç§ã䜿çšããŠããã³ãŒãã§ãã
import { ApolloClient, HttpLink, InMemoryCache } from '@apollo/client';
import { setContext } from '@apollo/link-context';
import AuthService from 'services/auth-service' // this is my implementation
const asyncAuthLink = setContext(async () => {
// this is an async call, it will be done before each request
const { token } = await AuthService.getCredentials();
return {
headers: {
authorization: token
},
};
},
);
const httpLink = new HttpLink({
uri: 'http://localhost:4000/graphql',
});
export const apolloClient = new ApolloClient({
cache: new InMemoryCache(),
link: asyncAuthLink.concat(httpLink),
});
@adrianolskããªãã¯æžããããµãŒãã¹ã³ãŒããæäŸã§ããŸãã
'services / auth-service'ããAuthServiceãã€ã³ããŒãããŸã//ããã¯ç§ã®å®è£
ã§ã
const {token} = await AuthService.getCredentialsïŒïŒ;
ãµãŒãã¹ãã€ã³ããŒãããããšãããšãšã©ãŒãçºçããŸã
ãããç§ã®ãµãŒãã¹ã§ããreact-nativeããAsyncStorageãèªã¿åãã ããªã®ã§ããã°ã€ã³åŸã«å€ãèšå®ããåãªã¯ãšã¹ãã®åã«ã³ãŒãã§æ å ±ãååŸããŠããããŒã«èšå®ããŸããåãããšãè¡ãããlocalStorageã䜿çšããŸãããŠã§ãäžã«ãããŸãã
䜿ãããæ å ±ã¯ã©ãã«ä¿åããŠããŸããïŒ
ããªãã¯ããã䜿ãããšãã§ããŸã
//save the token after login or when it refreshes
localStorage.setItem('token', yourToken);
ãããŠããã䜿çšããŸã
const asyncAuthLink = setContext(() => {
// grab token from localStorage
const token = localStorage.getItem('token');
return {
headers: {
authorization: token
},
};
},
);
@adrianolsk説æã«æè¬ããŸãããAngularã䜿çšããŠããŸãgrapqh.module.tsãã¡ã€ã«ã«ãµãŒãã¹ãã€ã³ããŒãã§ããŸãããµãŒãã¹ã䜿çšããŠãããšãã«ãšã©ãŒãçºçããŸã
ã¯ã©ã¹ãšã³ã³ã¹ãã©ã¯ã¿ãŒã䜿çšããã«module.tsãã¡ã€ã«ã§ãµãŒãã¹ã䜿çšããæ¹æ³ã誰ããç¥ãããšãã§ããŸã
ããããšã
ããŒã¯ã³ã®éåææŽæ°ã«fromPromise
ã䜿çšããããšããŠããŸãã
åºæ¬çã«ããã®æçš¿ã®3çªç®ã®ããã¯ã¹ã«ç¶ããŸã
ããŒã¯ã³ã®ååŸãšä¿åã«æåããŸãããã catch
ã filter
ã flatMap
åŒã³åºãããŸããã ããããããã°ããæ¹æ³ãããããªãã®ã§ãããã€ãã®ææ¡ã圹ç«ã¡ãŸãã
if (token && refreshToken) {
return fromPromise(
getNewToken(client)
.then(({ data: { refreshToken } }) => {
console.log("Promise data: ", refreshToken);
localStorage.setItem("token", refreshToken.token);
localStorage.setItem("refreshToken", refreshToken.refreshToken);
return refreshToken.token;
})
.catch((error) => {
// Handle token refresh errors e.g clear stored tokens, redirect to login, ...
console.log("Error after setting token: ", error);
return;
})
)
.filter((value) => {
console.log("In filter: ", value);
return Boolean(value);
})
.flatMap(() => {
console.log("In flat map");
// retry the request, returning the new observable
return forward(operation);
});
}
@adrianolsk ïŒãã®ã¢ãããŒãã¯ãæå¹æéãåããåã§ãã£ãŠããããŒã¯ã³ãåžžã«æŽæ°ããããã§ããäžéšã®èªèšŒãµãŒãã¹ïŒAuth0ã®checkSessionãªã©ïŒã®å ŽåãGraphQLãªã¯ãšã¹ãããšã«äžèŠãªAuth0ãµãŒããŒã®ã©ãŠã³ãããªãããçºçããŸãã
ããŒã¯ã³ã®éåææŽæ°ã«
fromPromise
ã䜿çšããããšããŠããŸãã
åºæ¬çã«ããã®æçš¿ã®3çªç®ã®ããã¯ã¹ã«ç¶ããŸãããŒã¯ã³ã®ååŸãšä¿åã«æåããŸãããã
catch
ãfilter
ãflatMap
åŒã³åºãããŸããã ããããããã°ããæ¹æ³ãããããªãã®ã§ãããã€ãã®ææ¡ã圹ç«ã¡ãŸããif (token && refreshToken) { return fromPromise( getNewToken(client) .then(({ data: { refreshToken } }) => { console.log("Promise data: ", refreshToken); localStorage.setItem("token", refreshToken.token); localStorage.setItem("refreshToken", refreshToken.refreshToken); return refreshToken.token; }) .catch((error) => { // Handle token refresh errors e.g clear stored tokens, redirect to login, ... console.log("Error after setting token: ", error); return; }) ) .filter((value) => { console.log("In filter: ", value); return Boolean(value); }) .flatMap(() => { console.log("In flat map"); // retry the request, returning the new observable return forward(operation); }); }
ãšã©ãŒã®åå ãèŠã€ããŸããã äžèšã®ã³ãŒãã«ã¯è¡šç€ºãããŠããŸãããã map
é¢æ°ã䜿çšããŠãçµæãšããŠçããåãšã©ãŒããããããŸããã ããã«ããã onError
ã¯äœãè¿ããããªãã¶ãŒããã«ã¯ããŒã¯ã³æŽæ°ã®æäœã«ãµãã¹ã¯ã©ã€ããããŸããã§ããã
ããªãæ··ä¹±ããŠããŠããããç解ããã®ã«ãšãŠãæéãããããŸããã ç§ãå©ããŠãããããã°æçš¿ã®äœè ã«æè¬ããŸãã
ERROR Error: Network error: Cannot read property 'length' of null
@ WilsonLau0755 ãç§ã¯åãåé¡ãæ±ããŠããŸããã ãã¹ãŠã®null
ããããŒã空ã®æåå''
èšå®ããããšã§è§£æ±ºããŸããã
onErrorãasyncawaitã§äœ¿çšã§ããã ãã§ã¯ãªãã®ã¯ãªãã§ããïŒ
æãåèã«ãªãã³ã¡ã³ã
onError
ã³ãŒã«ããã¯ãaync
é¢æ°ãåãå ¥ããªãããPromise
ãè¿ãããããã§ãã ã³ãŒãhttps://github.com/apollographql/apollo-link/blob/59abe7064004b600c848ee7c7e4a97acf5d230c2/packages/apollo-link-error/src/index.ts#L60-L74ãåç §ããŠãã®åé¡ã¯ä»¥åã«å ±åãããŸããïŒïŒ190
apollo-link-retry
ãããã§è¡ãã®ãšåæ§ã«ãapollo-link-error
ãPromise
ãåŠçã§ããã°ãããããŸããããšæããŸãïŒïŒ436