【发布时间】:2018-12-20 18:18:03
【问题描述】:
我有一个使用 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 代码,可以看到我的 fetchPolicy 在apollo-client/core/QueryManager.js(我的 cmets)的这段代码中被更改为“缓存优先” :
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 正在做什么的那行。
【问题讨论】:
-
你为什么要覆盖本地存储?带有几个方法的对象
-
>我在节点环境中运行(而不是反应):这是否意味着您无权访问窗口对象?
-
我做或不做都没有区别。它在 AWS 示例中,所以我在那个 sn-p 中添加以表明我已经尝试过了,但它实际上是从文档中复制和粘贴的。
标签: amazon-web-services apollo apollo-client aws-appsync