Apollo-link: Menggunakan pengambilan simpul dengan apollo-link-http

Dibuat pada 21 Feb 2018  ·  49Komentar  ·  Sumber: apollographql/apollo-link


Menggunakan HttpLink dengan pengambilan simpul memberikan kesalahan berikut:

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

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

Hasil yang diinginkan:
Menurut dokumentasi di atas seharusnya sudah dikompilasi.

Hasil sebenarnya:

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);

Cara mereproduksi masalah:
Versi berikut digunakan untuk menulis kode di atas.

    "@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"


Gunakan versi di atas dan buat instance HttpLink di TypeScript untuk melihat kesalahan di atas.

Komentar yang paling membantu

(Tindak lanjut pada 7 Mei 2018: cross-fetch kini hadir dengan definisi tipe TypeScript)

cross-fetch belum dikirimkan dengan definisi tipe TypeScript (juga @DefinitelyTyped).

Sambil menunggu lquixada/cross-fetch#12 digabungkan cross-fetch adalah alternatif, saya menemukan isomorphic-fetch bekerja dengan baik dengan HttpLink di TypeScript seperti sekarang:

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

const link = new HttpLink({
  fetch
})

Semua 49 komentar

Apa yang terjadi jika Anda menggunakan createHttpLink alih-alih new HttpLink ?

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

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

@dejayc Ini memberikan kesalahan yang sama ketika createHttpLink digunakan.

Sebenarnya, saya menemukan masalahnya. Node-fetch 2.x tidak kompatibel dengan _apollo-link_. Tanda tangan _fetch_ berbeda.

Node-fetch 2.x tidak kompatibel dengan apollo-link. Tanda tangan dari fetch berbeda.

Ah, saya kira Anda bisa meninju bebek itu.

Saya menemukan masalah ini hari ini di aplikasi isomorfik saya. Saya tidak sepenuhnya setuju dengan pengambilan global sebagai fallback default terutama pada hari-hari SSR ini, tetapi setidaknya kesalahannya agak informatif:

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';

Solusi saya adalah menggunakan node-fetch secara kondisional atau whatwg-fetch tergantung pada lingkungan node/browser. Atau cukup gunakan cross-fetch yang pada dasarnya melakukan hal yang sama.

Jadi...

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

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

@jmca Cara yang Anda sarankan untuk TypeScript berhasil untuk saya! Terima kasih!!

Saya mengalami masalah ini hari ini, dan mengetahui bahwa kami tidak kompatibel dengan node-fetch v2, saya yakin kami harus memperbaikinya.

Saya mulai menggunakan cross-fetch sekarang tetapi hanya mengimpor fetch: any ...

(Tindak lanjut pada 7 Mei 2018: cross-fetch kini hadir dengan definisi tipe TypeScript)

cross-fetch belum dikirimkan dengan definisi tipe TypeScript (juga @DefinitelyTyped).

Sambil menunggu lquixada/cross-fetch#12 digabungkan cross-fetch adalah alternatif, saya menemukan isomorphic-fetch bekerja dengan baik dengan HttpLink di TypeScript seperti sekarang:

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

const link = new HttpLink({
  fetch
})

Dokumentasi npmjs.com mendorong pengguna untuk menggunakan pengambilan simpul tetapi tidak menentukan versi mana. Bagaimana kami dapat memperbarui dokumentasi itu?

Catatan: menggunakan whatwg-fetch adalah solusi yang layak.

Apakah ada gerakan dalam hal ini?

Menggunakan cross-fetch sepertinya solusi yang aneh karena hanya menggunakan node-fetch . Bukankah itu sebenarnya masalah?

whatwg-fetch bukan solusi bagi kita di sisi server.

Jika seseorang membuka PR yang menyertakan definisi tipe yang tepat yang akan berfungsi dengan semua implementasi pengambilan tetapi mempertahankan beberapa pemeriksaan tipe, tolong @stubailo saya dan saya akan mencoba menggabungkannya!

@stubailo Pada Apollo Server kami menggunakan ini sebagai bagian dari apollo-server-env .

menggunakan HttpLink adalah opsional, ini berfungsi untuk saya:

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

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

Ada berita tentang ini? node-fetch masih menyebabkan masalah dengan apollo-link dan TS.

Ada berita? Masih mendapatkan masalah dengan node-fetch

Solusi untuk ini adalah tidak menginstal @types/node-fetch dan secara manual mendefinisikannya sebagai GlobalFetch sendiri.

Untuk melakukannya, tambahkan yang berikut ini ke file .d.ts di proyek Anda;

// 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;
}

Anda bisa menggunakan hal paksaan jenis as ...

Tentu, tetapi apa gunanya menginstal tipe sama sekali, jika Anda hanya akan memaksanya untuk melemparkannya ke sesuatu yang lain?
Mungkin juga menggunakan solusi saya dalam kasus itu.

Maaf, saya salah membaca apa yang Anda lakukan, abaikan komentar saya sebelumnya.

Namun, ini mengharuskan Anda memodifikasi tsconfig Anda untuk menargetkan browser, karena GlobalFetch hanya disediakan jika Anda memiliki "dom" sebagai entri di bidang "lib": https://github.com/apollographql/apollo-link/issues/ 273#issuecomment -347878009

Kedua, daripada memodifikasi secara manual .d.ts , tidak bisakah Anda meneruskan GlobalFetch['fetch'] ke konstruktor HTTPLink? Itu membuatnya jauh lebih sedikit tersembunyi.

  1. Tentu, tetapi untuk menyesuaikan dengan pengetikan HttpLink Anda harus menggunakan GlobalFetch['fetch'] terlepas dari itu, jadi saya tidak melihat jalan keluar dari persyaratan itu.

  2. Saya tidak mengikuti. GlobalFetch['fetch'] adalah tipe, bukan variabel.
    Maksud Anda mengimpor node-fetch dan kemudian mentransmisikannya ke GlobalFetch['fetch'] ?
    Itu bukan pilihan bagi saya karena saya mengaktifkan noImplictAny di proyek saya sehingga saya tidak dapat mengimpor apa pun yang tidak memiliki definisi.

Ini hanya solusi yang berhasil untuk saya ️, tetapi saya menyadari itu jauh dari sempurna (kata kunci: _workaround_).

Saya pikir solusi yang baik adalah dengan hanya mengubah pengetikan menjadi gabungan GlobalFetch['fetch'] dan tipe default ekspor pengambilan simpul.
Atau cukup ubah pustaka yang direkomendasikan ke lib pengambilan simpul yang TIDAK sesuai dengan GlobalFetch['fetch'] (whatwg-fetch atau apa pun).

  1. Ah, saya tidak menyadari itu diperlukan. TIL.

  2. Maaf, aku hanya sedang libur. Anda benar, itu tipe, bukan variabel.

https://www.npmjs.com/package/whatwg-fetch menyatakan dengan cukup eksplisit bahwa "Proyek ini tidak bekerja di bawah lingkungan Node.js. Ini dimaksudkan untuk browser web saja. Anda harus memastikan bahwa aplikasi Anda tidak mencoba untuk paket dan jalankan ini di server."

Ya, seseorang benar-benar harus memperbaiki bug dengan benar dengan memperbaiki jenisnya.

Setelah ditinjau lebih lanjut, ini tampaknya terutama merupakan masalah dengan node-fetch , jadi saya membuka masalah di atas. Sangat mungkin bahwa mereka akan memberitahu kita untuk hanya mengubah tipe kita.

Oke, node-fetch sepertinya menyuruh kita untuk hanya mengubah tipe kita. Satu peretasan adalah mengimpor tipe node-fetch dan menambahkannya sebagai solusi?

@grantwwu Maaf, hal-hal yang cukup sibuk dalam ikhtisar ke GraphQL Summit, tetapi kami baru-baru ini mulai menggunakan paket apollo-env yang mengekspor ulang node-fetch dengan jenis yang tepat: https://github .com/apollographql/apollo-tooling/tree/master/packages/apollo-env

(Kami mungkin ingin memisahkan ekspor pengambilan global)

Saya baru saja melakukan import { fetch } from 'apollo-env' dan saya _still_ mendapatkan kesalahan TypeScript saat meneruskannya ke konstruktor 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]'.

Saya berhasil menjalankan ini dalam pengujian saya:

import { fetch } from 'apollo-env'

......

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

Itu masih tidak bekerja untuk saya :/

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 versi apollo-http-link dan apollo-env mana yang Anda gunakan? Juga, ini dengan node, kan?

Ya, sama di sini. Menggunakan apollo-env tidak menyelesaikan masalah bagi saya.

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 : saya pakai
"apollo-klien": "^2.4.12",
"apollo-env": "^0.3.2",
"apollo-link-http": "^1.5.9",

Saya menggunakan benang untuk manajemen ketergantungan di aplikasi saya

Saya beralih ke graphql-request untuk proyek saya.

@jacobtani Seperti apa tampilan tsconfig Anda?

apollo-env masih berbeda dari yang diharapkan HttpLink. parameter input seharusnya tidak diperlukan

Saya akhirnya menimpanya seperti ini dan berhasil

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

Saya menggunakan ini dari simpul menggunakan ini

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

HARAP PATCH TIM DOCS APOLLO! Masalah ini sudah lebih dari satu tahun

@rlancer Saya menganggap ini masalahnya karena seperti yang disebutkan di atas komentar Anda, itu belum diperbaiki karena apollo-env membutuhkan tambalan. Ini bukan di repo ini tetapi di repositori apollo-tooling .

@JoviDeCroock Ada solusi yang berfungsi, dokumen harus menunjukkan untuk menggunakannya sebagai lawan dari solusi yang gagal dan memaksa orang ke Google untuk mencari solusi.

@JoviDeCroock apollo-env dan apollo-tooling memiliki deklarasi tipe pengambilan yang sama dan keduanya berbeda dari Global['fetch'] yang diharapkan oleh HttpLink. Tapi ini sepertinya bukan masalah, jika saya mendeklarasikan modul sendiri dengan deklarasi yang sama dengan apollo-env itu tidak mengeluh tentang tipe. Mungkin ekspornya tidak berfungsi

Yah, saya pribadi tidak pernah menggunakan ini. Jika Anda dapat mengarahkan saya ke solusi, saya dengan senang hati akan pr

Saya kira dengan membuat 2 jenis ini seharusnya berfungsi.

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

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

@jmca Terima kasih

@tafelito Terima kasih atas solusi Anda, itu sangat membantu, tapi saya pikir kesalahan sebenarnya ditemukan dan itu karena pembaruan TypeScript baru. Dalam versi 3.6, GlobalFetch dihapus dan WindowOrWorkerGlobalScope digunakan sebagai gantinya, jadi ini memaksa kita untuk menutup versi di dependensi package.json "typescript": "3.5.1" .

Ini linknya

Untuk menggemakan komentar di atas, repo saya harus tetap menggunakan TypeScript v3.5.3

Saya kira dengan membuat 2 jenis ini seharusnya berfungsi.

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

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

Saya sudah bisa memperbaikinya hanya menggunakan bagian kedua, terima kasih @tafelito

masalah yang sama.

"@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 });

Saya memiliki masalah yang sama di aplikasi saya. Saya memecahkan casting ke any seperti itu:

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

pada akhirnya masalahnya adalah bahwa node-fetch & pengetikan terkait sengaja menyimpang dari spesifikasi:

// 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;

jadi kesalahan kompiler tidak dapat dihindari jika Anda tidak menurunkan atau membuat pengetikan baru yang menghilangkan penambahan ini.

saya memilih untuk downcast node-fetch :

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

itu tidak bagus, tapi node-fetch != fetch, yang ...menggerutu... menyesatkan. node-fetch-like mungkin lebih tepat, dan membiarkan ekstensi _out_ dalam implementasi node-fetch dasar agar tetap sesuai dengan node-fetch akan membantu kami :)

Ini mungkin sama sekali tidak relevan ... tetapi ... memiliki masalah yang sama selama beberapa hari terakhir ... hanya untuk menyadari bahwa 'ambil' adalah sesuatu yang tersedia di browser, tetapi tidak di sisi server. Jika aplikasi Anda akan melakukan pengambilan dari browser, tidak ada gunanya melakukan pra-render koneksi di sisi server.

Dalam kasus saya, menggunakan NextJS, saya mengubah komponen yang memerlukan tautan http agar tidak dirender di sisi server sesuai https://nextjs.org/docs#with -no-ssr

Saya mengalami masalah yang sama, alih-alih menginstal node-fetch dan @types/node-fetch saya langsung menggunakan apollo-env dan bam! semua kesalahan hilang!

Saya berhasil membuatnya bekerja dengan isomorphic-fetch

package.json (semua versi dipilih untuk kompatibilitas dengan yang digunakan oleh 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",
.../mengetik/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" ],
...
kode
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
            })
          ])
        })
      });

Pertimbangkan cross-fetch !

Ini berfungsi dengan TypeScript dan node (bukan browser).

import fetch from 'cross-fetch'

const httpLink = new HttpLink({
  uri: "<your-uri>",
  fetch,
})
Apakah halaman ini membantu?
0 / 5 - 0 peringkat