Вот как работает мое приложение: я беру твиты из API и записываю их локально в файл json на сервере Apollo. Затем я хочу получить эти твиты с сервера Apollo с помощью GraphQL. К сожалению, кажется, что я не могу связать fetch и refetch (из запроса Apollo GraphQL). Когда я запускаю приведенный ниже код, я всегда получаю сообщение об ошибке Failed to load resource: Could not connect to the server. (когда я обновляюсь после ошибки, данные правильные). Однако, если в своей форме я запрашиваю только первый API, подождите несколько секунд и нажмите кнопку, подобную этой <button onClick = {() => refetch()}>Refetch!</button>, тогда все заработает.
Вот код:
let data = <Query
query = {gql`
{
twitQueries {
id
text
username
retweets
likes
}
}
`}
>
{ ({ loading, error, data, refetch }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error</p>;
const tweets = <div> my tweets </div>;
return <div id='formAndTweets'>
<button onClick = {() => refetch()}>Refetch!</button>
<form onSubmit = {(e) => {
e.preventDefault();
const username = this.state.username;
const controller = new AbortController();
const signal = controller.signal
fetch('http://localhost:5000/user/'+username+'/max/10', {
method: 'GET', signal: signal
}).then((res) => {
return res.json().then((data) => {
this.setState({request: 'done'});
return refetch();
});
});
}}>
<label htmlFor = "username">Username: </label>
<input id = "username" name = "username" type = "text" value = {this.state.username} onChange = {(e) => { this.setState({username: e.target.value}); }}/>
<input type = "submit" value = "Search" />
</form>
{tweets}
</div>
}}
</Query>
Почему я не могу сделать что-то вроде fetch(...).then(() => { refetch() }) и как решить эту проблему, не дожидаясь и нажимая другую кнопку?
ОБНОВЛЕНИЕ: он работает с общедоступным сервером Apollo. Так что, должно быть, что-то происходит с моим, но я не могу найти что. Вот код:
index.js:
import express from 'express';
import bodyParser from 'body-parser';
import { graphqlExpress, graphiqlExpress } from 'apollo-server-express';
import { makeExecutableSchema } from 'graphql-tools';
import path from 'path'
import fs from 'fs'
import cors from 'cors'
import resolvers from './resolvers'
const typeDefs = fs.readFileSync(path.join(__dirname, 'model.graphql'),{encoding:'utf-8'})
const myGraphQLSchema = makeExecutableSchema({typeDefs, resolvers})
const PORT = 4000;
const app = express();
app.use(cors()); // enable `cors` to set HTTP response header: Access-Control-Allow-Origin: *
// bodyParser is needed just for POST.
app.use('/graphql', bodyParser.json(), graphqlExpress({
schema: myGraphQLSchema,
}));
app.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
}),
);
app.listen(PORT);
resolver.js:
var exec = require('child-process-promise').exec;
const util = require('util');
const fs = require('fs');
const readFile = util.promisify(fs.readFile)
//updated by the first API
const testJsonPath = 'tweets.json';
const resolvers = {
MyQueryType: {
twitQueries(root,args,context) {
return readFile(testJsonPath).then(content =>{
return JSON.parse(content);
})
}
}
}
export default resolvers;
model.graphql
scalar Date
type TweeterQuery{
id: String
username: String
}
type Twit{
id: ID!
username: String!
date: String!
replies: Int!
retweets: Int!
likes: Int!
geo: String
mentions: String
hashtags: String
permalink: String!
emoticons: Int!
emoticonsStr: String
replying: Int!
replyingTo: String
text: String!
}
type Member{
id: ID!
login: String
}
type MyQueryType{
twitQueries(id: ID):[Twit]
}
schema{
query: MyQueryType
#mutation: Mutation
#subscription: Subscription
}
input TwitInput{
author:AuthorInput
}
input AuthorInput{
id:ID
login:String
}
Это действительно меня пугает, потому что, как я уже сказал, он действительно работает, если подождать несколько секунд после первого fetch. Я просто не могу понять, где проблема на моем сервере.
@DanielRearden ошибка появляется после завершения первого fetch. Это GraphQL refetch выходит из строя, первый всегда проходит. Это действительно странно, потому что это действительно должно работать на бумаге. Я вижу ошибку в консоли.
Если вы закомментируете вызов refetch, предотвратит ли это появление ошибки? Я не уверен, почему цепочка обещаний имеет здесь значение, но вам также не хватает return перед res.json().
@DanielRearden Я добавил возврат, и результат тот же. Если я прокомментирую refetch(), ошибки не будет. Как я уже сказал, я могу прокомментировать это, отправить свою форму, физически подождать 2 секунды и нажать кнопку для повторной загрузки, и она будет работать. Однако, если я имитирую JavaScript и нажму кнопку, как только будет выполнен первый fetch, будет выдана ошибка. Я не понимаю, зачем нужна такая задержка.
Вот простая песочница с использованием вашего кода, измененная для использования некоторых общедоступных API вместо тех, что указаны в вашем вопросе: codeandbox.io/s/8zn78k1qj0 Refetch работает должным образом. Так что, какова бы ни была проблема, она, скорее всего, находится за пределами этого кода.
@DanielRearden Вы правы, я пробовал использовать общедоступный сервер Apollo, и он работает. Я обновил свой пост. Что-то должно происходить с моим сервером, но я не могу понять это.
Позвольте нам продолжить обсуждение в чате.
@DanielRearden Я решил проблему, создав с нуля новый сервер Apollo (а не экспресс). Я понятия не имею, в чем заключалась точная проблема, но теперь она работает. Спасибо, что указали на то, что было не так!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Нет никаких причин, по которым
fetch(...).then(refetch)не должен работать. Где вы видите ошибку «Не удалось загрузить ресурс»? Можете ли вы увидеть на вкладке сети, какой из запросов не выполняется? Сам вызов fetch взрывается?