我有一个相当简单的Node应用程序,使用AWS AppSync。我能够成功运行查询和变异,但最近发现,如果我运行两次查询,即使我知道后端数据已更改,我也会得到相同的响应。在这种特定情况下,查询由lambda支持,在挖掘它时,我发现每次查询运行时查询似乎没有发送到网络上,因为lambda仅在第一次运行时触发。如果我使用控制台模拟我的查询,那么一切都正常运行。如果我重新启动我的应用程序,那么第一次查询运行正常,但是连续的查询每次都返回相同的值。
以下是我的部分代码:
这是从以下网址获取的:https://docs.aws.amazon.com/appsync/latest/devguide/building-a-client-app-javascript.html 使用此代码并在客户端设置中没有
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代码进行了调试,并可以看到我的fetchPolicy在
以下是我的部分代码:
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 SDK一起使用的正常IAM凭据的方法。这是有效的(否则我不会走得这么远)。
我的问题似乎与此问题非常相似GraphQL Query Runs Sucessfully One Time and Fails To Run Again using Apollo and AWS AppSync; 我正在使用Node环境(而不是React),但本质上是相同的问题。
我认为这并不重要,但为了完整起见,我应该提到我已经尝试过有和没有文档中的设置代码。这似乎没有任何区别(除了令人讨厌的日志记录,见下文),但在这里它是:
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代码进行了调试,并可以看到我的fetchPolicy在
apollo-client/core/QueryManager.js
中更改为'cache-first'(我的评论)。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的那行代码在做什么。