如何优化API的提取以减少冗余

3
我正在构建一个使用API的React应用程序,我现在构建的是两个函数,它们都会GET相同的URL,但会更改API终端的第二部分,例如URL/?searchURL/?i=123。但是我希望实现减少冗余代码,因此想要创建一个仅需要相同URL并基于调用更改URL第二部分的函数。

顺便说一下,这种方法给我带来了问题。
我最初编写的代码是这样的:
import {API_MOVIE_URL, API_KEY} from "./ApisConst";

export const getMoviesBySearch = async search => {
  try {
    const url = `${API_MOVIE_URL}?apikey=${API_KEY}&${search}`;
    const response = await fetch(url);
    const json = await response.json();
    return json;
  } catch {
    return {
      success: false,
      result: [],
      message: "There is an issue to get data from server. Please try again later.",
    };
  }
};

export const getMoviesInfo = async movieID => {
  try {
    const url = `${API_MOVIE_URL}?apikey=${API_KEY}&i=${movieID}&plot`;
    const response = await fetch(url);
    const json = await response.json();
    return json;
  } catch {
    return {
      success: false,
      result: [],
      message: "There is an issue to get data from server. Please try again later.",
    };
  }
};     

我尝试的更改是:

const fetchAPI = async ({type, query}) => {
  const queryParams = {
    byString: `&${query}`,
    byMovieId: `&i=${query}&plot`,
  };

  const endpoint = `${API_MOVIE_URL}?apikey=${API_KEY}${queryParams[type]}`;
  console.log("fetching", endpoint);

  return fetch(endpoint)
    .then(res => res)
    .catch(() => ({
      success: false,
      result: [],
      message: "There is an issue to get data from server. Please try again later.",
    }));
};

export const getMoviesBySearch = async search =>
  await fetchAPI({type: "byString", query: search});

export const getMoviesInfo = async movieID =>
  await fetchAPI({type: "byMovieId", query: movieID});

但是这种第二种方法在控制台中给我一个错误,错误信息为:
Response {type: "cors", url: "https://www.omdbapi.com/?apikey=API_KEY&s=harry+potter&type=movie", redirected: true, status: 200, ok: true, }
body: (...)
bodyUsed: false
headers: Headers {}
ok: true
redirected: true
status: 200
statusText: ""
type: "cors"
url: "https://www.omdbapi.com/?apikey=API_KEY&s=harry+potter&type=movie"

第一种方法完美运行,但第二种方法不行,并在尝试寻找解决方案,但无法想到如何使代码更好地优化。


据我所知,您的代码唯一的问题是您意外地编写了.then(res => res)而不是.then(res => res.json())。您在控制台中看到的不是错误,而是响应对象。您随后调用.json()方法对其进行处理。 - user5734311
这是如何将一个对象转换为查询字符串的方法:https://dev59.com/enI-5IYBdhLWcg3wta1q#1714899。你可以轻松地将其扩展到你的`fetchAPI`函数中。 - user5734311
这是我的方法:https://jsfiddle.net/khrismuc/gut3bfxj/ - user5734311
1个回答

4

由于查询除了URL之外都是相同的,所以创建一个查询生成器(createMoviesQuery)来接受一个生成URL的函数(urlGenerator),并返回一个查询函数。

示例(未经测试):

import {API_MOVIE_URL, API_KEY} from "./ApisConst";

const createMoviesQuery = urlGenerator => async (...params) => {
  try {
    const url = urlGenerator(...params);
    const response = await fetch(url);
    const json = await response.json();
    return json;
  } catch {
    return {
      success: false,
      result: [],
      message: "There is an issue to get data from server. Please try again later.",
    };
  }
};

export const getMoviesBySearch = createMoviesQuery((search) => `${API_MOVIE_URL}?apikey=${API_KEY}&${search}`);

export const getMoviesInfo = createMoviesQuery((movieID) => `${API_MOVIE_URL}?apikey=${API_KEY}&i=${movieID}&plot`);

1
那个完美解决了 :) 但是我也在学习中,所以您可以简单地解释一下我的问题是什么,以及您对url生成器的方法是什么,这样我就可以在下一次理解它了。 - Jakub
我要给这个点踩,因为它只是重写了原始代码,没有提到原始代码的错误在哪里,而底部的两个函数在我看来实际上比以前更糟糕。 - user5734311
@ChrisG,我不太理解你的评论,但如果你认为这个解决方案不好,能否提出一个更好的方案呢?如果可能的话,我想找到最好的解决方法来解决我的问题。 - Jakub
他不是在抱怨我的代码,而是在抱怨你的代码为什么不能正常工作的原因不明。 - Ori Drori
为什么我更喜欢传递一个生成URL的函数,而不是在代码中创建URL?在剥离URL构建代码后,您可以看到您拥有一个通用的API函数。您可以使用它来生成电影API的查询函数,但也可以用于其他API。 - Ori Drori
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接