Apollo-link: استخدام node-fetch مع apollo-link-http

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


يؤدي استخدام HttpLink مع node-fetch إلى الخطأ التالي

import { HttpLink } from 'apollo-link-http';
import fetch from 'node-fetch';

const link = new HttpLink({
      fetch,
      uri: this.endPoint.toString(),
    });

النتيجة المنشودة:
وفقًا للوثائق المذكورة أعلاه ، يجب أن يتم تجميعها.

النتيجة الفعلية:

src/tw-algo-manager.ts:20:31 - error TS2345: Argument of type '{ fetch: (url: string | Request, init?: RequestInit | undefined) => Promise<Response>; uri: strin...' is not assignable to parameter of type 'Options | undefined'.
  Type '{ fetch: (url: string | Request, init?: RequestInit | undefined) => Promise<Response>; uri: strin...' is not assignable to type 'Options'.
    Types of property 'fetch' are incompatible.
      Type '(url: string | Request, init?: RequestInit | undefined) => Promise<Response>' is not assignable to type '((input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>) | undefined'.
        Type '(url: string | Request, init?: RequestInit | undefined) => Promise<Response>' is not assignable to type '(input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>'.
          Types of parameters 'url' and 'input' are incompatible.
            Type 'RequestInfo' is not assignable to type 'string | Request'.
              Type 'Request' is not assignable to type 'string | Request'.
                Type 'Request' is not assignable to type 'Request'. Two different types with this name exist, but they are unrelated.
                  Property 'context' is missing in type 'Request'.

20     const link = new HttpLink({
                                 ~21       fetch,
   ~~~~~~~~~~~~22       uri: this.endPoint.toString(),
   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~23     }); // const link = createHttpLink(linkOptions);

كيفية إعادة إظهار المشكلة:
يتم استخدام الإصدارات التالية لكتابة التعليمات البرمجية أعلاه.

    "@types/graphql": "^0.12.4",
    "@types/node-fetch": "^1.6.7",
    "apollo-cache-inmemory": "^1.1.9",
    "apollo-client": "^2.2.5",
    "apollo-link": "^1.2.0",
    "apollo-link-http": "^1.4.0",
    "graphql": "^0.13.1",
    "graphql-tag": "^2.8.0",
    "node-fetch": "^1.7.2",
    "react-apollo": "^2.0.4",
    "url": "^0.11.0"


استخدم الإصدارات أعلاه وأنشئ مثيل HttpLink في الكتابة المطبوعة لرؤية الخطأ أعلاه.

التعليق الأكثر فائدة

(المتابعة في 7 مايو 2018: يأتي الآن cross-fetch مع تعريفات نوع TypeScript)

لم يتم شحن cross-fetch مع تعريفات نوع TypeScript حتى الآن (ولاDefinitelyTyped).

أثناء انتظار دمج lquixada / cross-fetch # 12 ، cross-fetch هو بديل ، وجدت isomorphic-fetch يعمل بشكل جيد مع HttpLink في TypeScript حتى الآن:

import { HttpLink } from 'apollo-boost'
import fetch from 'isomorphic-fetch'

const link = new HttpLink({
  fetch
})

ال 49 كومينتر

ماذا يحدث إذا استخدمت createHttpLink بدلاً من new HttpLink ؟

import { createHttpLink } from 'apollo-link-http';
import fetch from 'node-fetch';

const link = createHttpLink({
      fetch,
      uri: this.endPoint.toString(),
    });

dejayc يعطي نفس الخطأ عند استخدام createHttpLink.

في الواقع ، لقد اكتشفت المشكلة. node-fetch 2.x غير متوافق مع _apollo-link_. توقيع _fetch_ مختلف.

node-fetch 2.x غير متوافق مع رابط أبولو. توقيع الجلب مختلف.

آه ، أعتقد أنه يمكنك البطة لكمة.

لقد صادفت هذه المشكلة اليوم في تطبيقي المتماثل. لا أتفق تمامًا مع أن الجلب العالمي هو البديل الافتراضي خاصة في أيام SSR هذه ، ولكن على الأقل كان الخطأ مفيدًا إلى حد ما:

Error: 
fetch is not found globally and no fetcher passed, to fix pass a fetch for
your environment like https://www.npmjs.com/package/nodefetch.

For example:
import fetch from 'nodefetch';
import { createHttpLink } from 'apollo-link-http';

كان الحل الخاص بي هو استخدام node-fetch أو whatwg-fetch مشروط اعتمادًا على بيئة العقدة / المتصفح. أو استخدم فقط cross-fetch الذي يقوم بنفس الشيء بشكل أساسي.

وبالتالي...

// Using TypeScript
import * as fetch from 'cross-fetch'
new HttpLink({ fetch })

// Or just...
// import 'cross-fetch/polyfill'

jmca الطريقة التي اقترحتها لـ TypeScript عملت معي! شكرا!!

واجهت هذه المشكلة اليوم ، واكتشفت أننا غير متوافقين مع node-fetch v2 ، أعتقد أنه يجب علينا إصلاح هذا.

أبدأ في استخدام cross-fetch الآن ولكنه يستورد fetch: any ...

(المتابعة في 7 مايو 2018: يأتي الآن cross-fetch مع تعريفات نوع TypeScript)

لم يتم شحن cross-fetch مع تعريفات نوع TypeScript حتى الآن (ولاDefinitelyTyped).

أثناء انتظار دمج lquixada / cross-fetch # 12 ، cross-fetch هو بديل ، وجدت isomorphic-fetch يعمل بشكل جيد مع HttpLink في TypeScript حتى الآن:

import { HttpLink } from 'apollo-boost'
import fetch from 'isomorphic-fetch'

const link = new HttpLink({
  fetch
})

تشجع وثائق npmjs.com المستخدمين على استخدام node-fetch لكنها لا تحدد الإصدار. كيف يمكننا تحديث تلك الوثائق؟

ملاحظة: يعد استخدام whatwg-fetch حلاً قابلاً للتطبيق.

هل كان هناك أي تحرك في هذا الشأن؟

يبدو استخدام cross-fetch حلًا غريبًا لأنه يستخدم node-fetch . أليست هذه في الواقع مشكلة؟

whatwg-fetch حلاً بديلاً لأولئك منا على جانب الخادم.

إذا قام شخص ما بفتح علاقات عامة تتضمن تعريفات النوع الصحيح التي ستعمل مع جميع تطبيقات الجلب ولكنها تحافظ على نوع معين من التحقق ، من فضلك stubailo me وسأحاول الدمج!

stubailo على خادم Apollo ، نستخدم هذا كجزء من apollo-server-env .

استخدام HttpLink اختياري ، وهذا يناسبني:

import ApolloClient from 'apollo-boost'
import 'isomorphic-fetch'

const client = new ApolloClient({
  uri: 'endpoint-url-here'
})

أي أخبار عن هذا؟ لا يزال node-fetch يسبب مشاكل مع apollo-link و TS.

أى اخبار؟ لا تزال تواجه مشكلات مع node-fetch

الحل البديل لهذا هو عدم تثبيت @types/node-fetch وتعريفه يدويًا على أنه GlobalFetch بنفسك.

للقيام بذلك ، قم بإضافة ما يلي إلى أي ملف .d.ts في مشروعك ؛

// real node-fetch types clash with apollo-link-http, so manually define it as globalfetch here.
declare module 'node-fetch' {
    const fetch: GlobalFetch['fetch'];
    export default fetch;
}

يمكنك فقط استخدام شيء إكراه من النوع as ...

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

آسف ، لقد أخطأت في قراءة ما كنت تفعله ، وتجاهل تعليقي السابق.

ومع ذلك ، هذا يتطلب منك تعديل tsconfig الخاص بك لاستهداف المتصفح ، حيث يتم توفير GlobalFetch فقط إذا كان لديك "dom" كإدخال في حقل "lib": https://github.com/apollographql/apollo-link/issues/ 273 # issuecomment -347878009

ثانيًا ، بدلاً من تعديل .d.ts يدويًا ، ألا يمكنك تمرير GlobalFetch['fetch'] إلى مُنشئ HTTPLink؟ هذا يجعلها أقل خفية.

  1. بالتأكيد ، ولكن للتوافق مع كتابة HttpLink ، يجب عليك استخدام GlobalFetch['fetch'] بغض النظر عن ذلك ، لذلك لا أرى أي طريقة للتغلب على هذا المطلب.

  2. أنا لا أتبع. GlobalFetch['fetch'] هو نوع وليس متغيرًا.
    هل تقصد استيراد node-fetch ثم تحويله إلى GlobalFetch['fetch'] ؟
    هذا ليس متاحًا بالنسبة لي لأن لدي noImplictAny ممكّنًا في مشاريعي لذا لا يمكنني استيراد أي شيء ليس له تعريف.

إنه مجرد حل بديل يناسبني 🤷‍♀️ ، لكنني أدرك أنه بعيد عن الكمال (الكلمة الرئيسية: _workaround_).

أعتقد أن الحل الجيد هو تغيير الكتابة إلى اتحاد GlobalFetch['fetch'] والنوع الافتراضي لتصدير node-fetch.
أو قم فقط بتغيير المكتبة الموصى بها إلى node fetch lib الذي يتوافق مع GlobalFetch['fetch'] (whatwg-fetch أو أيًا كان).

  1. آه ، لم أدرك أن هذا مطلوب. سمسم.

  2. آسف ، أنا فقط أمضي يومًا عطلة حقًا. أنت على حق ، هذا نوع وليس متغيرًا.

تنص https://www.npmjs.com/package/whatwg-fetch صراحةً على أن "هذا المشروع لا يعمل ضمن بيئات Node.js. إنه مخصص لمتصفحات الويب فقط. يجب التأكد من أن تطبيقك لا يحاول حزمة وتشغيل هذا على الخادم. "

نعم ، يجب على شخص ما إصلاح الخطأ بشكل صحيح عن طريق إصلاح الأنواع.

بعد إجراء مزيد من المراجعة ، يبدو أن هذه مشكلة بشكل أساسي مع node-fetch ، لذلك فتحت الإصدار أعلاه. ومع ذلك ، فمن الممكن تمامًا أن يطلبوا منا تغيير أنواعنا.

حسنًا ، يبدو أن node-fetch يخبرنا فقط بتغيير أنواعنا. سيكون أحد الاختراقات استيراد أنواع node-fetch وإضافة ذلك كحل بديل؟

grantwwu عذرًا ، الأمور محمومة جدًا في المتهدمة لقمة GraphQL ، لكننا بدأنا مؤخرًا في استخدام حزمة apollo-env التي تعيد تصدير node-fetch بالأنواع الصحيحة: https: // github .com / apollographql / أبولو-الأدوات / شجرة / ماستر / حزم / أبولو-إنف

(ربما نرغب في فصل صادرات الجلب العالمية على الرغم من ذلك)

لقد أنجزت للتو import { fetch } from 'apollo-env' وما زلت أتلقى أخطاء TypeScript عند تمريرها إلى مُنشئ HttpLink .

TSError: ⨯ Unable to compile TypeScript:
src/index.ts(20,31): error TS2345: Argument of type '{ uri: string; fetch: (input?: string | Request | undefined, init?: RequestInit | undefined) => Promise<Response>; }' is not assignable to parameter of type 'Options'.
  Types of property 'fetch' are incompatible.
    Type '(input?: string | Request | undefined, init?: RequestInit | undefined) => Promise<Response>' is not assignable to type '(input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>'.
      Types of parameters 'input' and 'input' are incompatible.
        Type 'RequestInfo' is not assignable to type 'string | Request | undefined'.
          Type 'Request' is not assignable to type 'string | Request | undefined'.
            Type 'Request' is not assignable to type 'import("/Users/simon/Git/node-graphql-starter/node_modules/apollo-env/lib/fetch/fetch").Request'.
              Types of property 'headers' are incompatible.
                Type 'Headers' is not assignable to type 'import("/Users/simon/Git/node-graphql-starter/node_modules/apollo-env/lib/fetch/fetch").Headers'.
                  Types of property 'values' are incompatible.
                    Type '() => IterableIterator<string>' is not assignable to type '() => Iterator<[string]>'.
                      Type 'IterableIterator<string>' is not assignable to type 'Iterator<[string]>'.
                        Types of property 'next' are incompatible.
                          Type '{ (value?: any): IteratorResult<string>; (value?: any): IteratorResult<string>; }' is not assignable to type '{ (value?: any): IteratorResult<[string]>; (value?: any): IteratorResult<[string]>; }'.
                            Type 'IteratorResult<string>' is not assignable to type 'IteratorResult<[string]>'.
                              Type 'string' is not assignable to type '[string]'.

تمكنت من الحصول على هذا للعمل في الاختبار الخاص بي:

import { fetch } from 'apollo-env'

......

function httpLink({ apiUrl, idToken }) {
  return new HttpLink({
    uri: apiUrl,
    headers: {
      authorization: `Bearer ${idToken}`,
    },
    fetch
  })
}

ما زالت لا تعمل لي: /

src/remoteSchemas.ts:54:45 - error TS2322: Type '(input?: RequestInfo, init?: RequestInit) => Promise<Response>' is not assignable to type '(input: RequestInfo, init?: RequestInit) => Promise<Response>'.
  Types of parameters 'input' and 'input' are incompatible.
    Type 'RequestInfo' is not assignable to type 'import("/Users/grant.wu/petuum/api-gateway/node_modules/apollo-env/lib/fetch/fetch").RequestInfo'.
      Type 'Request' is not assignable to type 'RequestInfo'.
        Type 'Request' is not assignable to type 'import("/Users/grant.wu/petuum/api-gateway/node_modules/apollo-env/lib/fetch/fetch").Request'.
          Types of property 'headers' are incompatible.
            Type 'Headers' is missing the following properties from type 'Headers': entries, keys, values, [Symbol.iterator]

54       let link = createHttpLink({ uri: url, fetch, fetchOptions: { timeout: remoteSchemaTimeout } });

jacobtani ما هي إصدارات رابط apollo-http و apollo-env التي

نعم نفسه هنا. استخدام apollo-env لا يحل المشكلة بالنسبة لي.

Argument of type '{ credentials: string; fetch: (input?: string | Request | undefined, init?: RequestInit | undefined) => Promise<Response>; uri: string; }' is not assignable to parameter of type 'PresetConfig'.
  Types of property 'fetch' are incompatible.
    Type '(input?: string | Request | undefined, init?: RequestInit | undefined) => Promise<Response>' is not assignable to type '(input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>'.
      Types of parameters 'input' and 'input' are incompatible.
        Type 'RequestInfo' is not assignable to type 'string | Request | undefined'.
          Type 'Request' is not assignable to type 'string | Request | undefined'.
            Type 'Request' is not assignable to type 'import("/Users/rahul/work/r3pi/vi-image-contours/node_modules/apollo-env/lib/fetch/fetch").Request'.
              Types of property 'headers' are incompatible.
                Type 'Headers' is missing the following properties from type 'Headers': entries, keys, values, [Symbol.iterator]

grantwwu : أنا استخدم
"apollo-client": "^ 2.4.12"،
"apollo-env": "^ 0.3.2"،
"apollo-link-http": "^ 1.5.9"،

أستخدم الغزل لإدارة التبعية في تطبيقي

لقد تحولت إلى طلب Graphql لمشروعي .

jacobtani كيف تبدو tsconfig الخاص بك؟

apollo-env مختلفًا عما يتوقعه HttpLink. يجب ألا تكون معلمة الإدخال مطلوبة

انتهى بي الأمر إلى تجاوز الأمر هكذا ونجح

declare module "apollo-env" {
  export function fetch(
    input: RequestInfo,
    init?: RequestInit,
  ): Promise<Response>;
}

أنا أستخدم هذا من العقدة باستخدام هذا

"apollo-env": "^0.3.3"
"apollo-link-http": "^1.5.11"

يرجى تصحيح DOCS APOLLO TEAM! هذه القضية عمرها أكثر من عام

rlancer أفترض أن هذا هو الحال لأنه كما ذكر أعلاه تعليقك ، لم يتم إصلاحه بعد لأن apollo-env يحتاج إلى تصحيح. هذا ليس في هذا المستودع ولكن في مستودع apollo-tooling .

JoviDeCroock هناك حلول تعمل ، يجب أن تشير المستندات إلى استخدامها بدلاً من الحل الذي يفشل ويجبر الأشخاص على استخدام Google للحصول على حلول بديلة.

JoviDeCroock كلا من apollo-env و apollo-tooling لهما نفس إعلان أنواع الجلب وكلاهما يختلفان عن Global ['fetch'] الذي يتوقعه HttpLink. ولكن لا يبدو أن هذه هي المشكلة ، إذا أعلنت الوحدة بنفسي بنفس التصريح مثل apollo-env فلن تشكو من الأنواع. ربما لا يعمل التصدير

حسنًا ، أنا شخصياً لا أستخدمها أبدًا. إذا كنت تستطيع أن تدلني على حل ، فسيسعدني أن أعمل

أعتقد من خلال جعل هذين النوعين نفس الشيء يجب أن يعمل.

declare function fetch(
  input?: RequestInfo, ---> remove ?
  init?: RequestInit
): Promise<Response>;

declare interface GlobalFetch {
  fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
}

jmca شكرًا

tafelito شكرًا على الحل الذي GlobalFetch واستخدام WindowOrWorkerGlobalScope بدلاً من ذلك ، لذلك يجبرنا هذا على إغلاق الإصدار في تبعياتنا للحزمة. json "typescript": "3.5.1" .

ها هو الرابط

لتكرار التعليق أعلاه ، يجب أن يلتزم الريبو الخاص بي بـ v3.5.3

أعتقد من خلال جعل هذين النوعين نفس الشيء يجب أن يعمل.

declare function fetch(
  input?: RequestInfo, ---> remove ?
  init?: RequestInit
): Promise<Response>;

declare interface GlobalFetch {
  fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
}

لقد تمكنت من إصلاحه باستخدام الجزء الثاني فقط ، شكرًاtafelito

المشكلة نفسها.

"@types/node-fetch": "^2.5.0",
 "typescript": "^3.5.1"
"node-fetch": "^2.6.0",
error TS2345: Argument of type '{ uri: string; fetch: typeof fetch; }' is not assignable to parameter of type 'Options'.
  Types of property 'fetch' are incompatible.
    Type 'typeof fetch' is not assignable to type '(input: RequestInfo, init?: RequestInit | undefined) => Promise<Response>'.
      Types of parameters 'url' and 'input' are incompatible.
        Type 'RequestInfo' is not assignable to type 'import("/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/node_modules/@types/node-fetch/index").RequestInfo'.
          Type 'Request' is not assignable to type 'RequestInfo'.
            Type 'Request' is missing the following properties from type 'Request': context, compress, counter, follow, and 6 more.

8 const link = new HttpLink({ uri: 'http://localhost:3000', fetch });

لدي نفس المشكلة في طلبي. يمكنني حل عملية الإرسال إلى any هذا النحو:

import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-boost'
import { createHttpLink } from 'apollo-link-http'
import fetch from 'node-fetch'

const httpLink = createHttpLink({
//ISSUE: https://github.com/apollographql/apollo-link/issues/513
fetch: fetch as any,
uri: 'https://api.graph.cool/simple/v1/swapi',
})

const client = new ApolloClient({
link: httpLink,
cache: new InMemoryCache(),
})

export default client

في النهاية ، تكمن المشكلة في أن الكتابة node-fetch والكتابات المرتبطة بها تنحرف عمدًا عن المواصفات:

// copied directly from the @types/node-fetch
// https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/node-fetch/index.d.ts
Request {
   ...
    // node-fetch extensions to the whatwg/fetch spec
    agent?: Agent | ((parsedUrl: URL) => Agent);
    compress: boolean;
    counter: number;
    follow: number;
    hostname: string;
    port?: number;
    protocol: string;
    size: number;
    timeout: number;

لذا فإن أخطاء المترجم أمر لا مفر منه إذا لم تقم بالإحباط أو إنشاء كتابات جديدة تحذف هذه الإضافات.

اخترت تنزيل node-fetch :

import nodeFetch from 'node-fetch'
import { WhatWgFetch } from '../src/interfaces' // export type WhatWgFetch = typeof fetch
const fetch = (nodeFetch as unknown) as WhatWgFetch

إنه ليس رائعًا ، لكن node-fetch! = fetch ، وهو ... التذمر ... مضلل. ربما كان node-fetch-like أكثر ملاءمة ، وترك الامتدادات _out_ في تطبيق node-fetch الأساسي للحفاظ على توافق node-fetch كان من شأنه أن يفعل أمثالنا معروفًا :)

قد يكون هذا غير ذي صلة تمامًا ... ولكن ... واجهت نفس المشكلة في اليوم الأخير أو نحو ذلك ... فقط لإدراك أن "الجلب" شيء متاح في المتصفح ، ولكن ليس من جانب الخادم. إذا كان التطبيق الخاص بك سيقوم بالجلب من المتصفح ، فمن غير المجدي تقديم الاتصال مسبقًا على جانب الخادم.

في حالتي ، باستخدام NextJS ، قمت بتغيير المكون الذي يحتاج إلى رابط http حتى لا يتم عرضه على جانب الخادم وفقًا لـ https://nextjs.org/docs#with -no-ssr

كنت أواجه نفس المشكلة ، بدلاً من تثبيت node-fetch و @types/node-fetch ذهبت مباشرة مع apollo-env و bam! ذهب كل الأخطاء!

تمكنت من الحصول على هذا العمل مع الجلب المتماثل

package.json (تم تحديد جميع الإصدارات للتوافق مع تلك المستخدمة بواسطة appsync)
    "apollo-link": "1.2.3",
    "apollo-link-context": "1.0.9",
    "apollo-link-http": "1.3.1",
    "aws-appsync": "^3.0.2",
    "isomorphic-fetch": "^2.2.1",
...
    "@types/isomorphic-fetch": "0.0.35",
... / الكتابة / index.d.ts
declare function fetch(
  input?: RequestInfo,
  init?: RequestInit
): Promise<Response>;

declare interface GlobalFetch {
  fetch(input: RequestInfo, init?: RequestInit): Promise<Response>;
}
tsconfig.json
{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "lib": [ "dom",  "es6",  "esnext.asynciterable" ]
     ...
   },
  "types": [  "node", "aws-sdk"  ],
  "include": [ "./src/**/*.ts" ],
...
الشفرة
import * as fetch from 'isomorphic-fetch';

const client = new AWSAppSyncClient(appSyncClientOptions, {
        link: createAppSyncLink({
          ...appSyncClientOptions,
          resultsFetcherLink: ApolloLink.from([
            createHttpLink({
              fetch: fetch as GlobalFetch['fetch'],
              uri: appSyncClientOptions.url
            })
          ])
        })
      });

ضع في اعتبارك cross-fetch !

هذا يعمل مع عقدة ونسكربت (وليس متصفح).

import fetch from 'cross-fetch'

const httpLink = new HttpLink({
  uri: "<your-uri>",
  fetch,
})
هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات