vue.js 我从Graphql操场和前端得到不同结果

dm7nw8vv  于 2022-11-17  发布在  Vue.js
关注(0)|答案(2)|浏览(177)

我使用的是graphql、Vue.js和apollo
这是我的数据库

const sensorsdb = [
{
    name: "sensor 1",
    id: "s-1",
    timestamp: 1582021371,
    value: 100
},
{
    name: "sensor 1",
    id: "s-1",
    timestamp: 1579451703,
    value: 150
},
{
    name: "sensor 2-1",
    id: "s-2-1",
    timestamp: 1582021371,
    value: 200
},
{
    name: "sensor 2-2",
    id: "s-2-2",
    timestamp: 1579451703,
    value: 350
},
{
    name: "sensor 2-2",
    id: "s-2-2",
    timestamp: 1582021371,
    value: 300
},
{
    name: "sensor 3",
    id: "s-3",
    timestamp: 1582021371,
    value: 400
},];

我想根据对象id获取所有对象。sensorId是一个数组。因为我想获取具有多个id的多个对象。
下面是我用来获取对象的API函数。

async getDataById({ sensorId }) {
    let sensorsData = [];
    for (let i = 0; i < sensorId.length; i++) {
        let sensorData = this.sensorDataStore.sensors.filter(sensor => sensor.id === sensorId[i]);
        sensorsData = sensorsData.concat(sensorData);
    }
    return sensorsData;
}

在前端,gql文件如下:

query sensorData($id: [String]){
sensorData(id: $id){
    name
    id
    value
    timestamp
}}

使用vue.js中的apollo查询代码,在本例中selectedSensorId为[“s-2-1”,“s-2-2”]

<ApolloQuery :query="require('../graphql/sensorDataById.gql')" :variables="{ id: selectedSensorId }">
  <template v-slot="{ result: { loading, error, data } }">
    <b-loading :is-full-page=true :active.sync=loading :can-cancel="false"/>
    <div v-if="error">
      <no-data-error />
    </div>
    <div v-if="data">
      {{ data }}
      <bar-chart-view :sensorInfo="data.sensorData"/>
    </div>
  </template>
</ApolloQuery>

但我得到了如下不同的结果:具有正确结果的GraphqlPlayground重复传感器的前端结果-s-2 x1c 0d1x

qv7cva1a

qv7cva1a1#

Apollo Client根据文档中描述的id__typename字段对结果进行规范化。如果数组返回多个具有相同id的项,默认情况下它们将共享相同的缓存键,这意味着客户端返回的将是同一个对象。
您应该为InMemoryCache构造函数提供一个自定义的dataIdFromObject函数,以适应您的特定用例。

const dataIdFromObject = object => {
  switch (object.__typename) {
    case 'SensorDataPoint': return `SensorDataPoint:${object.id}:{value}`;
    default: return defaultDataIdFromObject(object);
  }
}

请注意,如果在其他地方使用相同的类型,可能会遇到该高速缓存在发生变化后正确更新的问题,因为我们现在同时关闭了valueid

type SensorDataPoint {
  id: ID!
  sensorId: ID!
  sensorName: String!
  value: Int!
  timestamp: Int!
}

甚至更好

type SensorDataPoint {
  id: ID!
  value: Int!
  timestamp: Int!
  sensor: Sensor!
}

type Sensor {
  id: ID!
  name: String!
}
zd287kbt

zd287kbt2#

我知道这已经有一段时间了,但正如丹尼尔Rearden上面提到的,我将{ addTypename: false }作为InMemoryCache的选项

const client = new ApolloClient({
  link: ApolloLink.from([
    onError(({ graphQLErrors, networkError }) => {
      if (graphQLErrors)
        graphQLErrors.forEach(({ message, extensions }) => {
          console.log(`[GraphQL error]: Message: ${message}, Code: ${extensions?.code}`)
        })
      if (networkError) {
        console.log(`[Network error] ->: ${networkError}`)
        Toast.show('Connection Error', {
          position: Toast.positions.TOP,
          type: 'danger',
          duration: 3000,
        })
      }
    }),
    authMiddleware,
    link,
  ]),
  cache: new InMemoryCache({ addTypename: false }),
});

相关问题