<p>خطأ أبولو في إرجاع الخطأ إلى المتصل</p>

تم إنشاؤها على ١٥ أبريل ٢٠١٩  ·  17تعليقات  ·  مصدر: apollographql/apollo-link

لذلك أنا أستخدم خطأ Apollo-link لإدارة الأخطاء العامة للمصادقة والمشرف. لكن إذا استخدمته ، فإن طرق الصيد في وعدي لا ترجع الأخطاء.

يبدو كما لو أن جميع الأخطاء تمر عبر خطأ apollo-link-error ولم يتم تمريرها مرة أخرى إلى طريقة المتصل.

هل هناك طريقة لإعادة الخطأ إلى المتصل حتى أتمكن من إدارة بعض الأخطاء محليًا وبعض الأخطاء عالميًا؟

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

لقد وجدت الحل غريبًا نوعًا ما ، لكنه:

هذا يطبع الرسالة فقط

  updateProfile: function() {
      this.$apollo
        .mutate({
          mutation: UPDATE_PROFILE,
          variables: current_user
        })
        .catch((error) => {
          console.log("this prints just the message", error);
        });
    }

لكن هذا يطبع المحتوى الكامل للأخطاء

  updateProfile: function() {
      this.$apollo
        .mutate({
          mutation: UPDATE_PROFILE,
          variables: current_user
        })
        .catch(({ graphQLErrors }) => {
          console.log("this prints the full content of 'errors'", graphQLErrors);
        });
    }

أعتقد أنه يمكن إغلاق هذه القضية
NosherwanromucciSceatlbrdar

ال 17 كومينتر

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

رمز بلدي:

  • في المزود:
const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(({ message, locations, path }) => {
        console.log(`[GraphQL error]: ${message}, Location: ${locations}, Path: ${path}`);
      },
    );
  }
});

const client = new ApolloClient({
  link: authLink.concat(errorLink).concat(httpLink),
  cache: new InMemoryCache(),
});

  • في المكون:
 loginMutation({ variables: { data } })
    .then(({ data, errors }) => {
      if (errors) {
        // I WANT TO BE ABLE TO READ ERROR MESSAGE HERE SO I CAN DISPLAY IT TO THE USER
      } else if (data) {
        ....
      }
    });

لاحظ أن استدعاء forward لن يساعد لأنه يعود غير محدد كوسيطة إلى then لذلك لن يكون لدي بيانات ولا خطأ ، وقم بتعيين errors إلى null أيضًا ليس خيار n لأنني في الواقع بحاجة إلى قراءة الأخطاء.

lbrdar هل وجدت أي حل بديل لهذا؟

كلا 😞

lbrdar أليست الطريقة للقيام بذلك هي من خلال الصيد؟

 loginMutation({ variables: { data } })
    .then(({ data, errors }) => {
      if (errors) {
        // I WANT TO BE ABLE TO READ ERROR MESSAGE HERE SO I CAN DISPLAY IT TO THE USER
      } else if (data) {
        ....
      }
    }).catch(errors => {

    });

lbrdarromucci أواجه نفس المشكلة. هل انتهى الأمر يا رفاق بحل هذا؟

Nosherwan لقد قمت للتو بتثبيت الإصدار 1.1.11 وكل شيء يعمل بشكل جيد الآن ... يمكنك أيضًا التحقق من

merksam شكرا لك على التعليق.
أنا أستخدم نفس الإصدار الذي تستخدمه بالضبط. لسوء الحظ ، السلوك هو نفسه.

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(({ message, locations, path }) => {
        console.log(`[GraphQL error]: ${message}, Location: ${locations}, Path: ${path}`);
      },
    );
  }
});

في كتلة التعليمات البرمجية أعلاه ، يتم اكتشاف أخطاء GraphQLE ويمكن عمل شيء ما في معالج onError. لكن هذه الأخطاء لا تنتقل إلى وعد الاستدعاء الفعلي.
أنا أستخدم وظائف غير متزامنة ، لذا بدلاً من "إذن" ، أستخدم كلمة رئيسية انتظار ، وهذا داخل كتلة try catch.
اكتشفت كتلة catch الخطأ ، ولكن لم يتم تمرير أي خطأ إليها.

هل وجد شخص ما أي حل لهذا؟

Nosherwan @ prem-prakash هل يمكننا الاتصال نجاحها في حالتي وليس في حالتك؟ (إذا كانت لا تزال ذات صلة)

لقد وجدت الحل غريبًا نوعًا ما ، لكنه:

هذا يطبع الرسالة فقط

  updateProfile: function() {
      this.$apollo
        .mutate({
          mutation: UPDATE_PROFILE,
          variables: current_user
        })
        .catch((error) => {
          console.log("this prints just the message", error);
        });
    }

لكن هذا يطبع المحتوى الكامل للأخطاء

  updateProfile: function() {
      this.$apollo
        .mutate({
          mutation: UPDATE_PROFILE,
          variables: current_user
        })
        .catch(({ graphQLErrors }) => {
          console.log("this prints the full content of 'errors'", graphQLErrors);
        });
    }

أعتقد أنه يمكن إغلاق هذه القضية
NosherwanromucciSceatlbrdar

ماذا عن إضافة هذا إلى الوثائق؟

آسف ولكن الحل أعلاه لا يعمل. أعتقد أن هناك مثالاً كاملاً حول كيفية إعادة إرسال GraphqlErors في خطأ الارتباط إلى المتصل الأولي.

في حالتي ، عندما يكون هناك خطأ ، لا يحصل كائن ApolloQueryResult التالي على تفاصيل الخطأ في onError. البعض في المحاولة ... قبض حول المكالمة. لا يمكن الحصول على تفاصيل الرسم البياني للخطأ من الخادم. مجرد "خطأ 400" ..

const gqlResult: ApolloQueryResult<IGReturnData<
            IAllDataTypes
        >> = await apolloClient.query<IGReturnData<IAllDataTypes>, TVariables>({
            query: queryGql,
            variables: queryVariables,
            errorPolicy: "all",
        });

تكوين الخادم:

const errorLink = onError(({ graphQLErrors, networkError }) => {
    if (graphQLErrors)
        graphQLErrors.forEach(({ message, locations, path }) =>
            console.log(
                `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`,
            ),
        );

    if (networkError) console.log(`[Network error]: ${networkError}`);
});

const httplink = new HttpLink({
    uri: "/graphql",
    credentials: "include",
});

const links = [errorLink, httplink];

export const apolloClient = new ApolloClient({
    link: ApolloLink.from(links),
    cache: new InMemoryCache({ addTypename: false, fragmentMatcher }),
});

@ بريم براكاش شكرا .... المنقذ ..

هذه المشكلة مزمنة للغاية. ليس لدي سيطرة على خادم Graphql في مشروعي ، فقط العميل. يستجيب الخادم مع وجود أخطاء في الرسم البياني بالشكل الصحيح ، ولكن برمز الحالة 400. في ارتباط الخطأ ، يمكنني الوصول إلى graphQLErrors ، ولكن في طفرة المكون ، عندما أسحب graphQLErrors كما اقترحه @ prem-prakash ، فإن graphQLErrors مصفوفة فارغة . يمكنني فقط الوصول إلى الرسالة الافتراضية "خطأ: خطأ في الشبكة: الاستجابة غير ناجحة: تم استلام رمز الحالة 400". يقوم Apollo بضرب رسائل الخطأ التي يمكن قراءتها من الخادم ("المستخدم أو كلمة المرور غير صحيحة") لأن رمز الحالة 400 هو نقطة توقف كاملة لـ Apollo.

هل هناك أي شخص يمكنه التعامل بنجاح مع استجابة رمز الحالة 400 مع رسائل الخطأ ، وتمرير تلك الرسائل إلى واجهة المستخدم في المكون الذي يسمى الطفرة؟

حسنًا ، لدي نهج غير معقول إلى حد ما ، لكنه يعمل:

أنا أقوم بتعيين hasGraphError منطقيًا في ذاكرة التخزين المؤقت ، وأيضًا تخزين رسالة الخطأ مؤقتًا.

const errorLink = onError(({ graphQLErrors, networkError }) => {
  if (graphQLErrors) {
    graphQLErrors.forEach(error => {
      // log gql error(s)
      console.log("[GraphQL error]: ", error);
      // cache error
      client.writeData({
        data: {
          hasGraphError: true,
          currentGraphError: error.message
        }
      });
    });
  }
  if (networkError) {
    // log network errors
    console.log("[Network error]: ", networkError);
  }
});

ثم في أحد مكونات MutationError ، أستعلم في ذاكرة التخزين المؤقت عن وجود خطأ ورسالة الخطأ ، وعرض خطأ gql أو خطأ حقيقي في الشبكة بشكل مشروط:

const HAS_ERROR = gql`
  query IsGraphErrorPresent {
    hasGraphError <strong i="11">@client</strong>
    currentGraphError <strong i="12">@client</strong>
  }
`;
export default function MutationError({ error }) {
  const { data } = useQuery(HAS_ERROR);
  const defaultErrorMessage =
    "We're having trouble connecting. Please check your internet connection and try again.";

  // real network error
  if (error && error.message.includes("Failed to fetch")) {
    return <Error>{defaultErrorMessage}</Error>;
  }

  // graph error
  if (error && data && data.hasGraphError) {
    return <Error>{data.currentGraphError}</Error>;
  }

  // probably a real server/network error
  if (error) {
    return <Error>{defaultErrorMessage}</Error>;
  }

  return null;
}

سيكون هذا عالميًا لأنني في حاجة إليه في جميع الطفرات نظرًا لأن خادمي _ دائمًا_ يعود 400 لما يجب أن يكون 200 + خطأ في الرسم البياني (أنا ممل قليلاً بشأن ذلك) ...

لذا فإن الشيء المهم هنا ، هو أنه في كل طفرة مكونة ، أستخدم رد اتصال onError فارغًا يمنع استثناءًا غير معالج من Apollo ، وعند النجاح يجب أن أتذكر إعادة تعيين hasGraphError المنطقي في ذاكرة التخزين المؤقت:

  const [someMutation, { loading, error, client }] = useMutation(SOME_MUTATION, {
    onError() {
      // this callback prevents apollo from throwing
      // ...unhandled exception on 400 status code
    },
    onCompleted({ someMutation }) {
      client.writeData({
        data: {
          hasGraphError: false
        }
      });
    }
  });

ثم يأخذ مكون خطأ الطفرة خطأ useMutation كدعامات (كلاهما يسمح بتحديد أخطاء الشبكة الحقيقية ، ويتأكد من أننا لا نعرض خطأ gql العام المخزن مؤقتًا على المكون الخطأ):

  {loading && <Spinner />}
  {error && <MutationError error={error} />}

كما قلت ، هذا النهج غير معقول إلى حد كبير ، لكنه يعمل حاليًا على حل:

  1. بشكل عام تكون قادرًا على معالجة أخطاء Graphql في واجهة المستخدم حتى إذا كانت الاستجابة تحتوي على رمز حالة غير 200
  2. على وجه التحديد أن تكون قادرًا على تمرير الأخطاء من تكوين apollo-link-error إلى مكون الاستدعاء ، لتقديمها في واجهة المستخدم

مشكلات هذا النهج على أنها مشفرة: يقوم هذا فقط بكتابة آخر خطأ GQL في المصفوفة إلى ذاكرة التخزين المؤقت ، لذلك فهو لا يدعم أخطاء GQL المتعددة في نفس الوقت. يجب أن يكون هذا سهل الإدارة إلى حد ما ، من خلال إنشاء مجموعة من الأخطاء ، وتخزينها في ذاكرة التخزين المؤقت ، ولكن سيتعين عليك تحديد مخطط / محللات محلية للقيام بذلك ، أو ربما فقط JSON. مخبأ كسلسلة. ستحتاج أيضًا إلى مسح خطأ GraphError الحالي في ذاكرة التخزين المؤقت للنجاح ، بدلاً من مجرد تعيين قيمة منطقية على خطأ.

أتمنى أن يساعد شخص ما!

أيضًا ، في حالة المساعدة ، لاحظ أن errorPolicy حاليًا لا تعمل على خطافات useMutation ، وهذا خطأ ، وقد تمت معالجته مؤخرًا في هذا PR: https://github.com/apollographql/apollo-client/pull/5863 ، ولكن لم يتم إصداره في هذا الوقت.

أي تقدم في هذا من المطورين؟

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات