我有一个使用AWS AppSync的相当简单的节点应用程序。我能够成功运行查询和变异,但是最近发现,如果我运行两次查询,我将得到相同的响应-即使我知道后端数据已更改。在这种特殊情况下,查询由lambda支持,在深入研究中,我发现查询似乎并没有在网络上发送出去,因为lambda不会在每次查询运行时触发-只是第一次。如果我使用控制台模拟查询,则一切运行正常。如果我重新启动应用程序,则在第一次运行查询时它可以正常运行,但是连续的查询再次每次都返回相同的值。
这是我的代码的一部分:
client.query({
query: gql`
query GetAbc($cId: String!) {
getAbc(cId: $cId) {
id
name
cs
}
}`,
options: {
fetchPolicy: 'no-cache'
},
variables: {
cid: event.cid
}
})
.then((data) => {
// same data every time
})
修改:尝试使用其他network-only
这样的抓取策略没有明显区别。
这是我设置客户端的方式,虽然不是超级干净,但似乎可以正常工作:
const makeAWSAppSyncClient = (credentials) => {
return Promise.resolve(
new AWSAppSyncClient({
url: 'lalala',
region: 'us-west-2',
auth: {
type: 'AWS_IAM',
credentials: () => {
return credentials
}
},
disableOffline: true
})
)
}
getRemoteCredentials()
.then((credentials) => {
return makeAWSAppSyncClient(credentials)
})
.then((client) => {
return client.hydrated()
})
.then((client) => {
// client is good to use
})
getRemoteCredentials
是一种将IoT身份验证转换为可与其他AWS开发工具包一起使用的常规IAM凭证的方法。这是可行的(因为如果没有的话,我将无法做到。)
我的问题似乎与此GraphQL Query Runs Sucessfully One Time and Fails To Run Again using Apollo and AWS AppSync类似;我在节点环境中运行(而不是做出反应),但这实际上是相同的问题。
我认为这无关紧要,但出于完整性考虑,我已经尝试过使用和不使用文档中的设置代码。这似乎没有什么区别(烦人的日志记录除外,请参见下文),但在这里是
global.WebSocket = require('ws')
global.window = global.window || {
setTimeout: setTimeout,
clearTimeout: clearTimeout,
WebSocket: global.WebSocket,
ArrayBuffer: global.ArrayBuffer,
addEventListener: function () { },
navigator: { onLine: true }
}
global.localStorage = {
store: {},
getItem: function (key) {
return this.store[key]
},
setItem: function (key, value) {
this.store[key] = value
},
removeItem: function (key) {
delete this.store[key]
}
};
require('es6-promise').polyfill()
require('isomorphic-fetch')
这取自:https://docs.aws.amazon.com/appsync/latest/devguide/building-a-client-app-javascript.html
使用此代码,并且在客户端设置中没有offlineDisabled: true
的情况下,我看到此行在控制台上不断涌出:
redux-persist asyncLocalStorage需要一个全局localStorage对象。 请使用其他存储后端,或者这是通用的Redux 您可能应该有条件地像这样保留应用程序: https://gist.github.com/rt2zz/ac9eb396793f95ff3c3b
但是,此问题没有明显的区别。
更新:我对package.json的依赖关系,我在测试过程中已对其进行了升级,因此yarn.lock包含的更新版本比此处列出的要多。不过:https://gist.github.com/macbutch/a319a2a7059adc3f68b9f9627598a8ca
更新#2 :我还从CloudWatch日志中确认,查询仅在一次上运行;我有一个在计时器上定期运行的变异,该变异已成功调用并在CloudWatch中可见。符合我的预期,但查询没有。
更新#3 :我已调试到AppSync / Apollo代码,并且可以在apollo-client/core/QueryManager.js
的此代码中看到将我的fetchPolicy更改为“缓存优先”(注释我的):
QueryManager.prototype.fetchQuery = function (queryId, options, fetchType, fetchMoreForQueryId) {
var _this = this;
// Next line changes options.fetchPolicy to 'cache-first'
var _a = options.variables, variables = _a === void 0 ? {} : _a, _b = options.metadata, metadata = _b === void 0 ? null : _b, _c = options.fetchPolicy, fetchPolicy = _c === void 0 ? 'cache-first' : _c;
var cache = this.dataStore.getCache();
var query = cache.transformDocument(options.query);
var storeResult;
var needToFetch = fetchPolicy === 'network-only' || fetchPolicy === 'no-cache';
// needToFetch is false (because fetchPolicy is 'cache-first')
if (fetchType !== FetchType.refetch &&
fetchPolicy !== 'network-only' &&
fetchPolicy !== 'no-cache') {
// so we come through this branch
var _d = this.dataStore.getCache().diff({
query: query,
variables: variables,
returnPartialData: true,
optimistic: false,
}), complete = _d.complete, result = _d.result;
// here complete is true, result is from the cache
needToFetch = !complete || fetchPolicy === 'cache-and-network';
// needToFetch is still false
storeResult = result;
}
// skipping some stuff
...
if (shouldFetch) { // shouldFetch is still false so this doesn't execute
var networkResult = this.fetchRequest({
requestId: requestId,
queryId: queryId,
document: query,
options: options,
fetchMoreForQueryId: fetchMoreForQueryId,
}
// resolve with data from cache
return Promise.resolve({ data: storeResult });
如果我使用调试器将shouldFetch
的值更改为true,那么至少我看到一个网络请求传出并且lambda执行。我想我需要解压正在改变fetchPolicy的那一行在做什么。
答案 0 :(得分:3)
好的,我发现了问题。这是我的问题的代码缩写:
client.query({
query: gql`...`,
options: {
fetchPolicy: 'no-cache'
},
variables: { ... }
})
在这里看哪里出了问题要容易一些。这应该是这样:
client.query({
query: gql`...`,
fetchPolicy: 'network-only'
variables: { ... }
})
原件中的两个问题:
fetchPolicy: 'no-cache'
在这里似乎不起作用(我得到的答复是空的)fetchPolicy
放在options
对象中graphql客户端指定选项的方式有所不同,我们正在两者之间进行切换。
答案 1 :(得分:2)
在AWS Lambda函数中运行时,将查询foreach
设置为$source1 = "Y:\New Documents\test.txt"
foreach ($line in Get-Content $source1) {
$find = $line
(Get-Content $source1).replace($find,"") |
Set-Content $source1
}
。
我建议对fetch-policy
,'network-only'
和WebSocket
使用替代,因为这些对象实际上并不适用于Lambda函数。我通常在Lambda中用于NodeJS应用程序的设置如下所示。
window
答案 2 :(得分:0)
对于每个查询或/和初始化客户端,有两个选项可启用/禁用AppSyncClient / ApolloClient的缓存。
客户端配置:
client = new AWSAppSyncClient(
{
url: 'https://myurl/graphql',
region: 'my-aws-region',
auth: {
type: AUTH_TYPE.AWS_MY_AUTH_TYPE,
credentials: await getMyAWSCredentialsOrToken()
},
disableOffline: true
},
{
cache: new InMemoryCache(),
defaultOptions: {
watchQuery: {
fetchPolicy: 'no-cache', // <-- HERE: check the apollo fetch policy options
errorPolicy: 'ignore'
},
query: {
fetchPolicy: 'no-cache',
errorPolicy: 'all'
}
}
}
);
替代:查询选项:
export default graphql(gql`query { ... }`, {
options: { fetchPolicy: 'cache-and-network' },
})(MyComponent);
有效的fetchPolicy值为:
cache-first
不同,此fetchPolicy始终会通过网络接口执行查询,readQuery()
仅在查询数据不在缓存中时才执行查询。此提取策略可优化用户的响应速度,同时还可以使缓存的数据与服务器数据保持一致,但需要额外的网络请求。readFragment()
和{{1}}方法。复制自:https://www.apollographql.com/docs/react/api/react-hoc/#graphql-options-for-queries