Reactjs 反应阿波罗链接-承诺解决后如何推进操作?
因此,我想出了如何设置一个中间件来处理我的身份验证令牌,并在需要时获取新的身份验证令牌。问题在于,这里存在一种边缘情况,即在承诺得到解决后,操作在未设置正确的头的情况下被转发,导致另一个可能未经验证的调用。我觉得这里的诀窍很简单,但我似乎不明白。有没有一种方法可以将承诺的结果返回到所包含的函数?我在这方面运气不太好,但也许还有别的办法。以下是设置我的中间件和Apollo客户端的代码:Reactjs 反应阿波罗链接-承诺解决后如何推进操作?,reactjs,react-apollo,apollo-client,Reactjs,React Apollo,Apollo Client,因此,我想出了如何设置一个中间件来处理我的身份验证令牌,并在需要时获取新的身份验证令牌。问题在于,这里存在一种边缘情况,即在承诺得到解决后,操作在未设置正确的头的情况下被转发,导致另一个可能未经验证的调用。我觉得这里的诀窍很简单,但我似乎不明白。有没有一种方法可以将承诺的结果返回到所包含的函数?我在这方面运气不太好,但也许还有别的办法。以下是设置我的中间件和Apollo客户端的代码: const authLink = new ApolloLink((operation, forward) =&g
const authLink = new ApolloLink((operation, forward) => {
operation.setContext(({ headers = {} }) => {
const token = localStorage.getItem('token');
const tokenExp = token ? decodeJWT(token).exp : null;
const currentTime = Date.now() / 1000;
if(token && tokenExp >= currentTime) {
// Check if token is expired. If so, get a new one and THEN
// move forward
headers = { ...headers,authorization: token ? `Bearer ${token}` : "", };
return { headers };
} else {
// TODO: This would be replaced with the token service that actually
// takes an expired token and sends back a valid one
return fetch('http://localhost:4000/topics', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `mutation LOGIN_USER(
$email: String
$password: String!
) {
login(email: $email, password: $password) {
id
token
}
}
`,
variables: {
email: "test@test.com",
password: "test"
}
}),
}).then(response => {
return response.json()
})
.then(({ data: { login: { token } }}) => {
// Put updated token in storage
localStorage.setItem('token', token);
headers = { ...headers,authorization: token ? `Bearer ${token}` : "", };
return { headers };
});
}
});
return forward(operation);
});
/**
* Setup the URLs for each service
*/
const httpTopicsServiceLink = createHttpLink({
uri: 'http://localhost:4000/topics',
});
/**
* Create the client instance for each GraphQL server URL
*/
export const TopicsClient = new ApolloClient({
link:authLink.concat(httpTopicsServiceLink),
cache: new InMemoryCache(),
});
您可以返回自己的承诺,该承诺将通过标头或获取请求中的另一个承诺进行解析:
const authLink = new ApolloLink(async (operation, forward) => {
return await operation.setContext(({ headers = {} }) => {
const token = localStorage.getItem('token');
const tokenExp = token ? decodeJWT(token).exp : null;
const currentTime = Date.now() / 1000;
return new Promise((resolve, reject) => {
if(token && tokenExp >= currentTime) {
// Check if token is expired. If so, get a new one and THEN
// move forward
headers = { ...headers,authorization: token ? `Bearer ${token}` : "", };
resolve({ headers });
} else {
// TODO: This would be replaced with the token service that actually
// takes an expired token and sends back a valid one
resolve(fetch('http://localhost:4000/topics', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
query: `mutation LOGIN_USER(
$email: String
$password: String!
) {
login(email: $email, password: $password) {
id
token
}
}
`,
variables: {
email: "test@test.com",
password: "test"
}
}),
}).then(response => {
return response.json()
})
.then(({ data: { login: { token } }}) => {
// Put updated token in storage
localStorage.setItem('token', token);
headers = { ...headers,authorization: token ? `Bearer ${token}` : "", };
return { headers };
}));
}
});
}).then(res => {
return forward(operation);
});
});
无法测试这一点,因此我可能遗漏了一些内容,但这应该确保在转发之前完成请求。如果
setContext
返回承诺,您不能添加然后语句并转发到那里吗?这是什么意思?我尝试向操作中添加一个.then,但我收到错误消息,告诉我未定义的无法读取属性'then
:/感谢您的响应,但不幸的是,我收到未定义的无法读取属性'then'。我曾尝试过类似的方法,将整个operation.setContext包装在一个Promise中。虽然我认为函数必须返回一个可观察的,而不是简单地调用forward(operation)
hmmmedit:我误解了。如果Apollo链接回调可以是异步的?你可以等待
setContext。更新我的答案,值得一试!谢谢你的努力?我在胡闹,然后尝试了你的版本,我得到了转发(…)。订阅不是一个函数
错误哈哈。我在做别的事情时也犯了同样的错误。我甚至试着用from
fromrxjs
将整个东西包装起来,但没有成功:P