国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

21 分鐘學 apollo-client 系列:請求攔截和 FragmentMatcher

Eastboat / 2640人閱讀

摘要:分鐘學是一個系列,簡單暴力,包學包會。接管了請求和狀態管理。一般在生產環境中,我們通常還希望做權限驗證請求攔截等事務處理。

21 分鐘學 apollo-client 是一個系列,簡單暴力,包學包會。

搭建 Apollo client 端,集成 redux
使用 apollo-client 來獲取數據
修改本地的 apollo store 數據
提供定制方案

請求攔截

封裝修改 client 的 api
apollo store 存儲細節

寫入 store 的失敗原因分析和解決方案

我們已經搭建了最小化的 ApolloClient。

Apollo 接管了 api 請求和狀態管理。一般在生產環境中,我們通常還希望做權限驗證、請求攔截等事務處理。

于是,我們就需要通過 Apollo 提供的一些接口,結合自己的業務需求,定制自己的 Apollo。

網絡層

GraphQL 入門: Apollo Client - 網絡層

上面這篇文章中,介紹了 Apollo 網絡層的基礎知識,推薦閱讀。我只是再做一些補充。

fetch

Apollo 使用的是 fetch api
從源碼來看,apollo 代碼中并沒有包含 polyfill,也就是說,在低版本的瀏覽器上可能會因為缺少 fetch 而失敗。所以你需要安裝 isomorphic-fetch
另外,如果你碰到跨域等問題,也是 fetch 引起的,和 apollo 沒什么關系。

const networkInterface = (createNetworkInterface({
    uri: "...",
    opts: {
        // fetch 相關的設置在這里配置
        credentials: "same-origin",
    },
}));
network middlewares

如果你使用過 Express 的話,就能很容易理解這個概念。否則你也可以理解為 middleware 就是請求的攔截器,可以在每個請求發送前或發送后,攔截請求,對其做一些修改,再決定是否傳遞,也可以直接取消。

所以你可以在這里

設置 headers

權限驗證

取消請求

緩存請求

實踐中,建議把所有的 middlewares 寫到一個多帶帶的文件。
我個人比較喜歡寫簡化的代碼,你也可以參考我進行配置。

middlewares.js

const wrapMiddlewares = (key) => (mws) => mws.map(mw => ({ [key]: mw }));
const wrapBeforewares = wrapMiddlewares("applyMiddleware");
const wrapAfterwares = wrapMiddlewares("applyAfterware");

// 可以看成一個沒有冗余代碼的配置表
export default function applyApolloMiddlewares(networkInterface) {
    networkInterface.use(wrapBeforewares([
        setHeaders,
    ]))
    .useAfter(wrapAfterwares([
        checkAuth,
    ]));

    return networkInterface;
}

// ---- 請求前 ----

function setHeaders(req, next) {
    try {
        if (!req.options.headers) {
            req.options.headers = {
                "Content-Type": "application/json;charset=utf-8",
            };
        }
    } catch (e) {
        console.error(e);
    }

    // 必須返回 next
    next();
}

// ---- 請求后 -----

function checkAuth({ response: res }, next) {
    try {
        // 自行處理 401 等各種 statusCode
    } catch (e) {
        console.error(e);
    }

    next();
}

建議對所有的 middlewares 包裹一層 try catch,因為我發現 apollo 這個庫不能很好地報錯,經常靜默失敗。

于是你的 createApolloClient 函數可以改寫為

createApolloClient.js

import { ApolloClient, createNetworkInterface } from "react-apollo";
import applyApolloMiddlewares from "./middlewares";

const networkInterface = (createNetworkInterface({
    uri: "...",
    opts: {
        // fetch 相關的設置在這里配置
        credentials: "same-origin",
    },
}));

const client = new ApolloClient({
    networkInterface: applyApolloMiddlewares(networkInterface),
});

return client;
FragmentMatcher

正式請求中,如果你的 schema 包含了 union type,形如

content { # 類型為 Content
    ... on Article {
        id
        title
    }
    ... on Timeline {
        id
        content
    }
}

即根據返回數據的類型不同,抓取不同的數據,這在 GraphQL 中,使用的是 inline fragment 語法來解決。
而上面代碼中的 Content 這個類,本身沒有具體字段,但有許多子類,被稱為 union type

可以看看 GraphQL 關于這一細節的描述:inline-fragments。

apollo 中使用一種啟發式的類型搜索方式,不像后端已經存在所有的類型說明,前端為了類型安全,必須由你來告訴 apollo,該 union type 下到底有哪些子類

否則你可能會看到這樣的報錯

You are using the simple (heuristic) fragment matcher, but your queries contain union or interface types.
     Apollo Client will not be able to able to accurately map fragments

報錯信息會指引你閱讀這個文檔,說的就是我上面描述的情況:Using Fragments on unions and interfaces

為了少寫垃圾代碼,我寫了一些 helper,希望對你有用。

const createIntrospectionFactory = (kind) => (name, possibleTypes) => ({
    name,
    kind,
    possibleTypes: possibleTypes.map(typename => ({ name: typename })),
});

const createInterface = createIntrospectionFactory("INTERFACE");
const createUnion = createIntrospectionFactory("UNION");

export default {
    introspectionQueryResultData: {
        __schema: {
            types: [
                createInterface("Content", [
                    "Article",
                    "Timeline",
                ]),
            ]
        }
    }
};

所以你的 client 可以寫成

import { ApolloClient, createNetworkInterface, IntrospectionFragmentMatcher } from "react-apollo";
import applyApolloMiddlewares from "./middlewares";
import fragmentMatcher from "./fragmentMatcher";

export default function createApolloClient() {
    const networkInterface = (createNetworkInterface({
        uri: "...",
        opts: {
            credentials: "same-origin",
        },
    }));

    const client = new ApolloClient({
        networkInterface: applyApolloMiddlewares(networkInterface),
        fragmentMatcher: new IntrospectionFragmentMatcher(fragmentMatcher),
    });

    return client;
}








文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/91923.html

相關文章

  • 21 分鐘 apollo-client 系列:擴展 ApolloClient 的 api

    摘要:分鐘學是一個系列,簡單暴力,包學包會。那怎么辦呢本章就教你非常簡單地實現擴展的。我們可以借鑒的的寫法,為的實例添加一些自己的方法。更重要的是,也會有的效果,上一個的輸出會成為下一個的輸入,便于組合。 21 分鐘學 apollo-client 是一個系列,簡單暴力,包學包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數據修改本地的 ...

    levy9527 評論0 收藏0
  • 21 分鐘 apollo-client 系列:apollo store 存儲細節

    摘要:分鐘學是一個系列,簡單暴力,包學包會。內部通過自己的私有沒有暴露給開發者來更新這個。相當于這個就是自己維護的,它將所有通過得到的數據保存在這里。的生成規則根據官方文檔的說法,在創建時,可選設置。如果不存在,則可能出現。 21 分鐘學 apollo-client 是一個系列,簡單暴力,包學包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來...

    lavor 評論0 收藏0
  • 21 分鐘 apollo-client 系列:簡單搭建

    摘要:分鐘學是一個系列,簡單暴力,包學包會。其中提到了等需要后端配合的東西,徒增了配置的復雜性。如果不行,再跟隨我的簡單步驟試試。環境要求請確保你已經搭建了自己的環境下文在行號前添加表示刪除的原代碼,表示新增的代碼。 21 分鐘學 apollo-client 是一個系列,簡單暴力,包學包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數據...

    ranwu 評論0 收藏0
  • 21 分鐘 apollo-client 系列:寫入失敗的原因解決方案

    摘要:分鐘學是一個系列,簡單暴力,包學包會。一旦你丟失了,可能會導致寫入失敗,或者盡管寫入了,但本該攜帶的那一層的數據沒有寫入。 21 分鐘學 apollo-client 是一個系列,簡單暴力,包學包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數據修改本地的 apollo store 數據提供定制方案 請求攔截 封裝修改 clie...

    Baoyuan 評論0 收藏0
  • 21 分鐘 apollo-client 系列:獲取數據

    摘要:分鐘學是一個系列,簡單暴力,包學包會。一旦組件掛載后,會自動進行數據請求,前提是客戶端提供的和后端的相符。如果回調返回直接不作請求。在組件內進行分頁請求之前提到了,這個裝飾器為添加了對象,其中有個函數為。 21 分鐘學 apollo-client 是一個系列,簡單暴力,包學包會。 搭建 Apollo client 端,集成 redux使用 apollo-client 來獲取數據修改本...

    robin 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<