Apollo-link: Bagaimana cara menangani permintaan async?

Dibuat pada 9 Okt 2017  ·  3Komentar  ·  Sumber: apollographql/apollo-link

Hai teman-teman, bersemangat untuk rilis Apollo Client 2.0 yang akan datang! Saya mencoba untuk bermigrasi ke versi beta, dan saya mengalami kesulitan dalam menyiapkan middleware auth saya. Token autentikasi saya disimpan di aplikasi RN saya melalui AsyncStorage, yang (Anda dapat menebaknya), tidak sinkron. Sebelumnya ini bukan masalah, karena ini adalah kode middleware yang saya gunakan untuk menyuntikkan token auth ke header:

const authMiddleware = {
    async applyMiddleware(req, next) {
        if (!req.options.headers)
            // Create the header object if needed.
            req.options.headers = {};

        // Inject the auth header if it exists
        const authExists = await Storage.authToken.exists();

        if (authExists) {
            const token = await Storage.authToken.get();
            req.options.headers['Authorization'] = `Bearer ${token}`;
        }

        next();
    }
};

Sekarang saya telah beralih ke implementasi Tautan baru, seperti yang didokumentasikan di sini :

const authLink = new ApolloLink(async (operation, forward) => {
    const authExists = await Storage.authToken.exists();

    if (authExists) {
        const token = await Storage.authToken.get();

        operation.setContext({
            headers: {
                Authorization: `Bearer ${token}`
            }
        });
    }

    return forward(operation);
});

Satu-satunya masalah tampaknya perpustakaan baru tampaknya tidak menyukai kata kunci async . Ketika saya menghapusnya dan mengomentari semua kecuali pernyataan pengembalian, saya mendapatkan (seperti yang diharapkan) kesalahan 403 dari server saya. Namun, dengan kata kunci yang ditambahkan saya mendapatkan:

Network error: undefined is not a function (near '..._this.inFlightRequestObservables[key].subscribe...')

Saya membayangkan ini ada hubungannya dengan fakta bahwa objek permintaan mengembalikan janji alih-alih nilai yang diharapkan. Apakah ada pendekatan yang bisa memperbaiki ini?

Hasil yang diinginkan:

Aplikasi harus menerapkan middleware meskipun menggunakan janji.

Hasil sebenarnya:

Kesalahan di atas muncul jika kata kunci async ada.. bahkan tanpa itu.. Anda masih harus mengembalikan panggilan forward() di dalam metode then() , yang akan tidak bekerja.

Cara mereproduksi masalah:

Saya percaya menambahkan async ke fungsi permintaan dari setiap panggilan konstruktor ApolloLink akan melakukannya.

Komentar yang paling membantu

Semua 3 komentar

Jadi dengan cukup mengutak-atik, saya benar-benar dapat memperbaiki sendiri:

const authLink = new ApolloLink((operation, forward) => {
    return new Observable(observable => {
        let sub = null;

        Storage.authToken.exists().then(exists => {
            if (exists) {
                Storage.authToken.get().then(token => {
                    operation.setContext({
                        headers: {
                            Authorization: `Bearer ${token}`
                        }
                    });

                    sub = forward(operation).subscribe(observable);
                });
            } else {
                sub = forward(operation).subscribe(observable);
            }
        });

        return () => (sub ? sub.unsubscribe() : null);
    });
});

Yang mengatakan, saya sangat baru di perpustakaan ini jadi saya berharap implementasi saya tidak membuka pintu untuk kerentanan apa pun. Saya pikir karena sub hanya direferensikan dan tidak disalin, nilai null akan menjadi langganan yang tepat setelah Janji diselesaikan. Bagaimanapun, tutup untuk saat ini. Semoga kode ini membantu seseorang.

Namun saya mendapatkan kesalahan yang sama tanpa async pada constructor , tetapi async pada Observable 's constructor . Anda dapat menirunya sebagai berikut:

new ApolloLink(() => {
  return new Observable(async observer => {
    await new Promise((resolve, reject) => setTimeout(resolve, 1000))

    observer.next({data: {}})
    observer.complete()
  })
})

Atau langkah paling minimal untuk ditiru:

new ApolloLink(() => {
  return new Observable(() => {
    return new Promise()
  })
})

Sangat aneh seolah-olah saya membuka gulungan async / await sebagai berikut:

new ApolloLink(() => {
  return new Observable(observer => {
    const timeoutPromise = new Promise((resolve, reject) => setTimeout(resolve, 1000))

    timeoutPromise.then(() => {
      observer.next({data: {}})
      observer.complete()
    })
  })
})

Kemudian semuanya baik-baik saja.

Tampaknya perpustakaan Observable tidak menyukai AsyncFunction s (yang pada dasarnya sama dengan Promise yang dikembalikan)? Saya tidak akan menebak ini karena tidak masalah apa yang dikembalikan constructor selama observer.{next/complete/error/etc} dipanggil dalam constructor yang sesuai.

Beri tahu saya jika Anda memerlukan informasi tambahan. Senang membuka edisi terpisah untuk melacak ini juga.

Terima kasih!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat