Apollo-link-rest: كيفية الوصول إلى response.headers باستخدام Apollo-link-rest؟

تم إنشاؤها على ١١ نوفمبر ٢٠٢٠  ·  6تعليقات  ·  مصدر: apollographql/apollo-link-rest

أهلا بكم،

يجب أن أستخدم apollo-link-rest للوصول إلى بقية api ، ومع ذلك ، لا يمكنني الوصول لكل useQuery () إلى response.headers .

على سبيل المثال ، واجهة برمجة تطبيقات راحة مع ترقيم صفحات ، والتي تضع معلومات first, prev, next, last في رأس الصفحة. كيف يمكنني الوصول إلى ذلك؟

لقد قدمت مثالًا هنا: https://codesandbox.io/embed/how-to-access-response-0mqx7؟file=/src/Client.ts

يمكنك الانتقال إلى علامة التبويب أدوات التطوير Network ، شاهد الرد باستخدام الرؤوس ، في الرابط ، توجد معلومات ترقيم الصفحات. لكن ليس لدي أي فكرة عن كيفية الوصول إلى Headers ....

ها هو الكود الرئيسي ، ليس لدي فكرة ، كيف أحصل على response.headers.link ...

  const queryTodos = gql`
      query Todos($page: number, $limit: number) {
        todos(_page: $page, _limit: $limit)
          @rest(type: "[Todo]", path: "/todos/?{args}") {
            userId
            id
            title
            completed
        }
     }
   `;

export const Todos = () => {
  const { data, loading, error } = useQuery(queryTodos, {
    variables: { page: 1, limit: 3 },
    fetchPolicy: "no-cache"
  });

 ...

  return (<div>...</div>)

لقد طرحت أيضًا هذا السؤال في stackoverflow: https://stackoverflow.com/q/64791676/3279996 ، في حال كنت ممتنًا للحصول على المزيد من النقاط في stackoverflow. :د

enhancement enhancement💡 feature help wanted 🛠 question❔

ال 6 كومينتر

blatoo - للأسف ، هذه ميزة غير موجودة حاليًا في Apollo-link-rest.

بشكل أساسي ، لا تتوقع GraphQL التعامل مع الرؤوس - لأنه يجب أن تكون هذه الرؤوس قابلة للإرجاع في عمق الرسم البياني.

إذا أراد شخص ما تنفيذ ذلك ، فيمكنني رؤيتنا بإضافة __headers كحقل سري / تلقائي في "نص" الاستجابة ، ولكن يتعين علينا إضافة علامة ميزة لتمكين هذا السلوك ، و قم ببعض التغيير في مفاتيح الرأس بحيث تكون متوافقة مع Graphql.

const queryTodos = gql`
      query Todos($page: number, $limit: number) {
        todos(_page: $page, _limit: $limit)
          @rest(type: "[Todo]", path: "/todos/?{args}") {
+             __headers {
+                         XMyHeader
+             }
            userId
            id
            title
            completed
        }
     }
   `;

fbartho شكرا جزيلا على هذه الإجابة. ستكون ميزة رائعة ، إذا تمكنا من الوصول إلى معلومات الرأس. أستخدم خادم json ، وضعوا معلومات ترقيم الصفحات في Headers ، أيضًا لمعلومات ترقيم الصفحات المستندة إلى المؤشر.

بالمناسبة ، رأيت في وثائقك: خيارات responseTansformer و customFetch . هل يمكنني فعل شيء معهم للحصول على معلومات ترقيم الصفحات ؟؟؟ في الواقع لقد حاولت كثيرًا ولكن لم تنجح بعد ...:

https://www.apollographql.com/docs/link/links/rest/#response -transforming

https://www.apollographql.com/docs/link/links/rest/#custom -fetch

للأسف، apollo-link-rest تعتمد على apollo-link الصورة API إلى سد العجز في GraphQL - ولكن يعني ذلك أنني لا أعتقد أن هناك طريقة واضحة للمشاركة في JS Headers API مباشرة - ولكن قد يكون من الممكن إصدار نسخة غير طبيعية منه.

ومع ذلك ، يمكن استخدام خيارات responseTransformer أو customFetch لتصحيح ما تحتاجه.

و responseTransformer يتلقى JS Response الكائن الذي لديه response.headers السمة.

لذلك يمكنك كتابة شيء مثل هذا:

responseTransformer: async (resp: Response) => {
    const body = await resp.json();
    const interestingHeaders = {};
    interestingHeaders.headerOne = resp.headers.get("headerOne"); // Pluck out the headers you want
    body.__headers = interestingHeaders
    return body;
}

اعتمادًا على إصدار المستعرض الخاص بك ، قد تتمكن من استخدام headers.entries() للحصول على جميع الرؤوس ككائن واحد بدلاً من headers.get() - لكن هذا غير متوفر حاليًا في Safari-iOS.

من الواضح أن هذا مبسط ، ويتم ترك معالجة الأخطاء لك ، لكنني أعتقد أن هذا سينجح!

customFetch يمكنه أيضًا القيام بذلك ، لكنني أعتقد أن responseTransformer أسهل.

fbartho نجاح باهر ، هذا رائع! لقد جربت الكود الخاص بك للتو ، لقد نجح الأمر وحصلت على الرابط.

الآن تأتي مشكلة أخرى ، كيف يمكنني الوصول إلى الاستعلام body.__headers.link ؟

كود الاستعلام الخاص بي هو:

const queryTodos = gql`
  query Todos($page: number, $limit: number) {
    todos(_page: $page, _limit: $limit)
      @rest(type: "TodoPagination", path: "/todos/?{args}") {
      __headers {
        link
      }
      userId
      id
      title
      completed
    }
  }
`;

ولكن ما قيمة __headers خالية ...
الكود هنا: لقد أضفت الكود الخاص بك في Client.ts وكود الاستعلام موجود بـ Todo.tsx :
https://codesandbox.io/s/how-to-access-response-0mqx7؟file=/src/Todos.tsx

fbartho مرحبًا ، لقد جربت ثلاث طرق مختلفة ، أخيرًا ، لقد حللت هذه المشكلة أخيرًا. ومع ذلك ، ما زلت أشك في ما إذا كان هذا حلًا جيدًا. هل تستطيع أن تعطيني رأيك؟

الأسلوب 1: فشل.
في البداية ، أعتقد أنه يمكنني الاستعلام عن __headers في useQuery() ، حاولت عدة مرات ، لكنها فشلت.

الطريقة الثانية: لم أحاول ، لأنني أشك في الحل
قم بتغيير بنية الاستجابة في responseTransformer ، ضع __headers في مفتاح __headers وقم أيضًا بوضع قائمة المهام في مفتاح todo . ومع ذلك ، أعتقد أنه ليس حلاً جيدًا. لأنه سيتم تغيير كل بنية الاستجابة. لذلك لا بد لي من إعادة كتابة كل الهيكل في useQuery() .

الطريقة الثالثة: النجاح والميت البسيط
أضع __headers في متغير تفاعلي. في الدالة responseTransformer ، وضعت قيمة __headers في متغير تفاعلي ، واستعلم عنها بعد تنفيذ useQuery() . ومع ذلك ، ما زلت غير متأكد ، لأنه لا بد لي من عمل متغير تفاعلي مختلف لاستعلام مختلف ...

blatoo ، هذه مشكلة قديمة ، وحلتها بـ new ApolloLink

const paginationLink = new ApolloLink((operation, forward) => {
  return forward(operation).map((response) => {
    const context = operation.getContext();

    const { headers } = context.restResponses[0] || null;
    // in my case i'm making a bunch of sub queries, so i'm using `[0]` to get the headers from the top level.

    if (headers) {
      const pagination = getPaginationFromHeaders(headers.get('link'));

      return { ...response, data: { ...response.data, pagination } };
    }
    return response;
  });
});

const client = new ApolloClient({
  cache: new InMemoryCache(),
  link: concat(paginationLink, restLink),
});
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات