3. Apollo RESTDataSource
3m

我们知道我们的数据在哪里,也知道数据的结构。太棒了。现在从我们的!

我们的 需要访问那个 REST API。它可以使用 fetch,或者我们可以使用一个名为 DataSource 的便捷帮助类。这个类解决了直接方法中的一些挑战和限制。

Hand-drawn illustration depicting a GraphQL server deciding whether to use `fetch` or a data source to retrieve data from the REST API in data-land

为了更好地理解这些挑战和限制,让我们先从 fetch 开始,然后再创建 DataSource

在 Node.js 环境中调用 REST API 时,我们可能会使用像 axiosnode-fetch 这样的库。这些库提供了对 HTTP 方法的轻松访问以及良好的异步行为。

使用 node-fetch,从我们的 /tracks 端点检索所有曲目,看起来像这样:

fetch("apiUrl/tracks").then(function (response) {
// do something with our tracks JSON
});

这给了我们曲目数组,但我们仍然缺少作者信息。对于数组中的每个曲目,我们需要调用 /author/:id 端点,如下所示:

fetch(`apiUrl/author/${authorId}`).then(function (response) {
// this is the author of our track
});

假设我们的 /tracks 端点返回 100 首曲目。那么,我们需要进行一次调用来获取数组,然后进行 100 次额外的调用 来获取每个曲目的作者信息。

现在,如果我们这 100 首曲目都是同一个作者创作的?我们将会进行一次调用来获取曲目,检索我们的 100 首曲目,然后进行 100 次调用来获取完全相同的作者。

听起来效率很低,对吧?我们可以只进行两次调用,而最终却进行了 101 次调用。

这是一个典型的 N+1 问题。“1” 指的是获取顶级 tracks 的调用 ,而“N” 是获取每个曲目作者子字段的后续调用的次数。

{
tracks {
# 1
title
author {
# N calls for N tracks
name
}
}
}
是什么让 N + 1 问题效率低下?

此外,在我们的应用程序和这个特定的 中,我们并不希望主页频繁变化。也许每隔几周就会添加一首新曲目。利用缓存来避免不必要的 REST API 调用会很好。方便的是,我们的 REST API 已经为其端点设置了缓存头。

对于 ,一个 通常由来自不同端点、具有不同缓存策略的不同 和类型组成。那么,我们应该如何处理这种情况下缓存呢?

Hand-drawn illustration depicting the N + 1 problem with a query and a REST API

我们开始真正感受到我们简单的 fetch 方法的局限性。

为了解决这些问题,我们需要专门为 设计的工具,它将有效地处理 REST API 调用的资源缓存和重复数据消除。

并且,由于在构建 API 时从 REST 中获取数据是一项非常常见的任务,因此,Apollo 提供了一个 DataSource 类,专门用于此目的: RESTDataSource

通过在服务器上实现 RESTDataSource,我们刚刚看到的所有挑战都将开箱即用地得到解决。

资源缓存对于我们的数据源有什么用?

让我们看看如何在我们的 Catstronauts 应用程序中扩展和实现这个 RESTDataSource

上一步

分享您关于本课的问题和评论

您的反馈将帮助我们改进!如果您卡住或感到困惑,请告诉我们,我们会帮助您。所有评论都是公开的,必须遵守 Apollo 行为准则。请注意,已解决或已解决的评论可能会被删除。

您需要一个 GitHub 帐户才能在下面发布。没有帐户? 请在我们的 Odyssey 论坛上发布。