官网入口
环境:
前端:ng9 后端: nestjs
问题:
在初始化建立graphql连接时,后端拿不到前端传的登录信息。 ps: 只在ng9出现,ng8正常。
解决方案:
找到
直接看注释old method和new method
import { ActivatedRoute, Router } from '@angular/router';
import { HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { HttpLink } from 'apollo-angular-link-http';
import { onError } from 'apollo-link-error';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { setContext } from 'apollo-link-context';
import { ApolloLink } from 'apollo-link';
import { WebSocketLink } from 'apollo-link-ws';
import { getMainDefinition } from 'apollo-utilities';
import { OperationDefinitionNode } from 'graphql';
import { NgForage } from 'ngforage';
export interface CreateApolloParams {
httpLink: HttpLink;
ngForage: NgForage;
domainId: number;
router: Router;
activatedRoute: ActivatedRoute;
production: boolean;
uri: string;
wsUri: string;
}
export function createApollo(params: CreateApolloParams): any {
const { httpLink, ngForage, notification, domainId, production, uri, wsUri, router, activatedRoute } = params;
// Http link
const http = httpLink.create({ uri });
// Cached storage for the user token
let token;
// Authentication
const withToken = setContext(async () => {
// if you have a cached value, return it immediately
// if (token) { return token; } no using cached
token = await ngForage.getItem('TOKEN_DATA');
});
// Flow link
const authFlowLink = withToken;
// Middleware
const authMiddleware = new ApolloLink((operation, forward) => {
// add the authorization to the headers
// if (production) {
if (token) {
operation.setContext({
headers: new HttpHeaders().set('Authorization', `Bearer ${token}`)
});
}
// }
return forward(operation);
});
// Afterware
const afterwareLink = new ApolloLink((operation, forward) => {
return forward(operation).map(response => {
return response;
});
});
// Error link
const errorLink = onError(({ graphQLErrors, networkError, response }) => {
if (graphQLErrors) {
graphQLErrors.map(({ message, locations, path }) =>
console.error(
`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`
)
);
for (const err of graphQLErrors) {
// detail actions
}
}
}
if (networkError) {
console.error(`[Network error]:`, networkError);
if (networkError instanceof HttpErrorResponse) {
const httpErrorResponse: HttpErrorResponse = new HttpErrorResponse(networkError);
throw httpErrorResponse;
}
}
});
// Create a WebSocket link:
const ws = new WebSocketLink({
uri: wsUri,
options: {
reconnect: true,
/* old method
connectionParams: Authorization: `Bearer ${token}`
*/
// new method
connectionParams: () => {
return {
Authorization: `Bearer ${token}`,
};
}
}
});
const splitLink = ApolloLink.split(
// split based on operation type
({ query }) => {
const { kind, operation } = getMainDefinition(query) as OperationDefinitionNode;
return kind === 'OperationDefinition' && operation === 'subscription';
},
ws,
http
);
return {
link: ApolloLink.from([
authFlowLink,
authMiddleware,
afterwareLink,
errorLink,
splitLink
// http
]),
cache: new InMemoryCache({
// why? see
// https://stackoverflow.com/questions/48840223/apollo-duplicates-first-result-to-every-node-in-array-of-edges/49249163#49249163
dataIdFromObject: (o: any) => (o._id ? `${o.__typename}:${o._id}` : void (0))
}),
defaultOptions: {
watchQuery: {
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
},
query: {
fetchPolicy: 'network-only',
errorPolicy: 'all',
},
mutate: {
errorPolicy: 'all'
}
}
};
}
分析: 在新建WebSocketLink时,参数connectionParams可以是一个变量,也可以是一个方法的返回值,这里把变量改成函数就ok了。 当然,方法不唯一,并且目前国内用Graphql的人也比较少,相对来说挖坑的多于填坑的,这篇算是一个填坑记录吧。