點燈坊

失くすものさえない今が強くなるチャンスよ

使用 Vue Apollo 建立 Smart Subscription

Sam Xiao's Avatar 2019-12-17

GraphQL Subscription 最常使用的場景為原本 Smart Query 已經有資料,但經過 Subscription 通知後需更新原本資料,Vue Apollo 特別設計了 Smart Subscription,可在完全不知道 WebSocket 前提下,不知不覺使用 GraphQL Subscription。

Version

macOS Catalina 10.15.2
WebStorm 2019.3
Node 13.2.0
Vue CLI 4.1.1
Vue 2.6.10
Vue Apollo 3.0.0-beta.11

Vue Apollo

src/App.vue

<template>
  <div>
    <ul>
      <li v-for="(item, index) in books" :key="index">
        {{ item.title }}:{{ item.price }}
      </li>
    </ul>
  </div>
</template>

<script>
import gql from 'graphql-tag'

let query = gql`
  query {
    books {
      title
      price
    }
  }
`

let document = gql`
  subscription {
    bookAdded {
      title
      price
    }
  }
`

let updateQuery = ({ books }, { subscriptionData: { data: { bookAdded } } }) => ({
  books: [...books, bookAdded]
})

let books = {
  query,
  subscribeToMore: {
    document,
    updateQuery
  }
}

export default {
  name: 'app',
  apollo: {
    books
  }
}
</script>

44 行

export default {
  name: 'app',
  apollo: {
    books
  }
}

apollo property 下定義 books smart query。

第 3 行

<ul>
  <li v-for="(item, index) in books" :key="index">
    {{ item.title }}:{{ item.price }}
  </li>
</ul>

在 HTML template 內可直接使用 v-for 搭配 books smart query。

39 行

let books = {
  query,
  subscribeToMore: {
    document,
    updateQuery
  }
}

實踐 books smart query,原本只需定義 query property 即可,若還需 smart subscription,則還需定義 subscribeToMore property,其為 object,包含 documentupdateQuery 兩個 property。

  • query:定義 GraphQL query
  • document:定義 GraphQL subscription
  • updateQuery:定義當 subscription 觸發時須執行的 function

14 行

let query = gql`
  query {
    books {
      title
      price
    }
  }
`

定義 books smart query 的 GraphQL query。

23 行

let document = gql`
  subscription {
    bookAdded {
      title
      price
    }
  }
`

定義 books smart subscription 的 GraphQL subscription。

32 行

let updateQuery = ({ books }, { subscriptionData: { data: { bookAdded } } }) => ({
  books: [...books, bookAdded]
})

定義 books smart subscription 被觸發時所要執行的 function。

第一個 argument 為原本 books smart query 的資料。

第二個 argument 為 subscription 所回傳資料。

兩者都可使用 ES6 的 object destructuring 直接解構,最後再使用 array spread 組合成最新資料回傳。

Browser

smart000

原本 books smart query 只有 2 筆資料。

Insomnia

mutation {
  addBook(book: {
    title: "Speaking JavaScript"
    price: 300
  }) {
    title
    price
  }
}

使用 Insomnia 執行 addBook mutation,相當於在其他 client 執行 mutation 觸發 subscription。

smart001

Browser

smart002

原本 books smart query 自動更新成 3 筆資料。

Conclusion

  • Vue Apollo 讓我在收到 GraphQL subscription 後,不用再重新執行 GraphQL Query,只要實踐 updateQuery() 即可自動在背景更新原本資料,非常方便

Sample Code

完整範例可在我的 GitHub 上找到

Reference

Vue Apollo, Subscribe To More