使用 JavaScript 客户端库 (v2.0)

警告:本页面介绍的是 Google 的旧版 API,即 Google 数据 API;它仅与 Google 数据 API 目录中列出的许多 API 相关,其中许多 API 已替换为较新的 API。如需了解特定新 API,请参阅新 API 的文档。如需了解如何使用较新的 API 向请求授权,请参阅 Google 帐号身份验证和授权

本文介绍了如何使用 JavaScript 客户端库发送 Google Data API 查询以及解读返回的响应。

Google 提供了一组使用各种编程语言的客户端库,用于与具有数据 API 的服务进行交互。使用这些库,您可以构建 API 请求、将其发送到服务并接收响应。

本文档提供了一些关于使用 JavaScript 客户端库的常规信息,以及一组常见用途示例。

观众

本文档适用于想要编写可与 Google 数据服务进行交互的客户端应用的 JavaScript 程序员。

本文假定您了解 Google Data API 协议的一般概念。本文档还假定您知道如何使用 JavaScript 进行编程。

如需了解客户端库提供的类和方法,请参阅 JavaScript 客户端库 API 参考文档(采用 JSdoc 格式)。

本文档是按顺序阅读的,其中每个示例都基于早期的示例。

使用条款

您同意在使用 JavaScript 客户端库时遵守 Google JavaScript 客户端库使用条款

数据模型和控制流概览

JavaScript 客户端库使用一组类来表示 Google Data API 所使用的元素。

注意:数据的底层表示法是 JSON,但客户端库提供了一个抽象层,因此您无需直接使用 JSON 数据。如果您想直接使用 JSON,而不使用客户端库,请参阅将 JSON 与 Google Data API 配合使用

该库提供了一些方法,可让您异步向具有数据 API 的服务发送数据,以及从这些服务接收数据。例如,google.gdata.calendar.CalendarService.getEventsFeed() 方法会向 Google 日历发送 Feed 请求。您传递的其中一个参数是接续函数,也称为回调函数;服务通过调用连续函数,以 JSON 格式返回 Feed。然后,客户端可以调用各种 get 方法,以 JavaScript 对象的形式使用数据。

如需添加新条目,请使用客户端库的类和方法创建条目,然后调用 feed.insertEntry() 方法将新条目发送到服务。您再次提供延续函数,当成功添加条目时,服务会调用该函数。

如果您刚开始接触 JavaScript,控制流程可能会有些令人困惑。在大多数情况下,调用 getEventsFeed()insertEntry() 等方法后,脚本就会结束。当服务返回所请求的数据时,系统会在接续函数中执行。因此,客户端对返回的数据执行的任何操作都应在连续函数中完成,或从该函数调用。您可能需要将某些变量设为全局变量,以便在多个函数中使用。

如需详细了解此编程样式,请参阅维基百科中的“延续传递样式”。

关于受支持的环境

目前,我们仅支持在浏览器中的网页中运行的 JavaScript 客户端应用。目前支持的浏览器包括:

  • Firefox 2.x 和 3.x
  • Internet Explorer 6、7 和 8
  • Safari 3.x 和 4.x
  • Google Chrome(所有版本)

JavaScript 客户端库会处理与服务服务器的所有通信。如果您是一位有经验的 JS 开发者,您可能会想:“那么同源政策呢?”借助 JavaScript 客户端库,您的客户端可以从任何网域发送 Google 数据请求,同时仍符合浏览器安全模型的要求。

有关使用 Google 数据 API 进行身份验证的概述,请参阅 Google 数据 API 身份验证概览。本文档的其余部分假定您熟悉此系统的工作原理。

客户端应用示例

如需了解 JavaScript 客户端库的实际应用,请访问我们的示例页面

教程和示例

以下示例展示了如何使用 JavaScript 客户端库发送各种数据 API 请求。

为了让用户更有针对性,这些示例展示了如何与 Google 日历的特定服务交互。我们会指出 Google 日历与其他 Google 服务的不同之处,以帮助您调整这些示例,以便在其他服务中使用。要详细了解 Google 日历,请参阅 Google Calendar Data API 文档。

加载库

您的客户端必须先从服务器请求客户端库代码,然后才能使用客户端库。

首先,在 HTML 文档的 <head> 部分使用 <script> 标记获取 Google AJAX API 加载器:

<script type="text/javascript" src="https://www.google.com/jsapi"></script>

通过预加载库,您可以最大限度地减少与 Google 服务器之间的往返次数并缩短延迟时间。如需直接从 Google AJAX API 加载器中预加载某些软件包(而不使用 google.load()),请参阅下文:

<script type="text/javascript"
      src="https://www.google.com/jsapi?autoload=%7Bmodules%3A%5B%7Bname%3Agdata%2Cversion%3A2.x%2Cpackages%3A%5Bblogger%2Ccontacts%5D%7D%5D%7D"></script>

注意:脚本的 src 网址应完全经过网址编码。例如,上一个示例是
<script type="text/javascript" src="https://www.google.com/jsapi?autoload={modules:[{name:gdata,version:2.x,packages:[blogger,contacts]}]}"></script>

如果您没有自动加载模块,则可以使用 JavaScript 设置代码中的下一个示例,在获取通用加载器之后加载 Google Data 客户端库。必须通过 HTML 文档的 <head> 部分(或在 HTML 文档的 <head> 部分使用 <script> 标记添加的 JavaScript 文件)进行此调用:

google.load("gdata", "2");

或者,您也可以请求特定服务,而不是请求整个库。以下示例仅下载 Blogger 和通讯录的软件包:

google.load("gdata", "2.x", {packages: ["blogger", "contacts"]});

google.load() 的第二个参数是所请求的 JavaScript 客户端库的版本号。我们的版本编号方案是根据 Google Maps API 使用的方案进行建模。以下是可能的版本号及其含义:

"1"
主要版本 1 的倒数第二个修订版本。
"1.x"
主要版本 1 的最新修订版本。
"1.s"
主要版本 1 的最新稳定修订版本。根据开发者的反馈,我们偶尔会将某个版本的客户端库声明为“稳定”版本。但是,该版本可能并不具有最新的功能。
"1.0""1.1”等
库的特定版本,具有指定的主要和次要修订版本号。

调用 google.load() 后,您必须指示加载器等到网页加载完成后再调用代码:

google.setOnLoadCallback(getMyFeed);

其中 getMyFeed() 是本文档下一部分中定义的函数。请使用此方法,而不是将 onload 处理程序附加到 <body> 元素。

请求未经身份验证的 Feed

要请求未经身份验证的 Feed,请将以下代码添加到您的 JavaScript 文件中,或添加到 HTML 文件中的 <script> 标记中。

在下面的代码中,getMyFeed() 会先调用(由 AJAX API 加载器调用,如上一部分所述)。

它调用 setupMyService() 以创建与 Google 日历的连接(由 CalendarService 对象表示)。我们已将服务创建代码提取到单独的模块化模块中;之后,我们将根据您的身份验证选项修改 setupMyService() 函数。

设置该服务后,getMyFeed() 会调用客户端库的 getEventsFeed() 方法以请求 Feed。

我们将在全局变量中指定 Feed 网址,以便在后续函数中使用。在此示例中,我们使用的是名为 liz@gmail.com 的用户的公开(未通过身份验证)Feed 网址。您也可以使用 default 代替用户的电子邮件地址,来表示经过身份验证的用户。

var feedUrl = "http://www.google.com/calendar/feeds/liz@gmail.com/public/full";

function setupMyService() {
  var myService = new google.gdata.calendar.CalendarService('exampleCo-exampleApp-1');
  return myService;
}

function getMyFeed() {
  myService = setupMyService();

  myService.getEventsFeed(feedUrl, handleMyFeed, handleError);
}

请注意,我们会将 myService 设为全局变量,以便在后续函数中使用。

为了使上述代码在您自己的客户端中起作用,对于具有公开共享日历的日历帐号,您必须使用真实用户的电子邮件地址。

注意:当您创建新的 CalendarService 对象时,客户端库会调用一个名为 google.gdata.client.init() 的方法,用于检查客户端运行的浏览器是否受支持。如果发生错误,客户端库会向用户显示错误消息。如果您想自行处理此类错误,可以在创建服务之前明确调用 google.gdata.client.init(handleInitError),其中 handleInitError() 是您的函数。如果发生 init 错误,您的函数会收到标准 Error 对象;您可以对该对象执行所需的任何操作。

在对 getEventsFeed() 的调用中,第二个参数为 handleMyFeed,它是一个回调函数;请参阅下文。Google 日历会处理请求,如果请求成功,则会将包含回调的“feed root”对象传递给回调函数。Feed 根是包含 Feed 的容器对象。

getEventsFeed() 的第三个参数是一个可选的错误处理函数;如果客户端库遇到错误,它会调用指定的错误处理程序,而不是成功回调函数。客户端库将作为参数传递给错误处理程序的对象是 JavaScript Error 对象的实例,具有额外的 cause 属性。

以下是回调函数和错误处理程序的简单版本:

function handleMyFeed(myResultsFeedRoot) {
  alert("This feed's title is: " + myResultsFeedRoot.feed.getTitle().getText());
}

function handleError(e) {
  alert("There was an error!");
  alert(e.cause ? e.cause.statusText : e.message);
}

我们只需向用户显示这些错误即可进行处理;您客户端的错误处理程序应该会更加复杂。在某些情况下,可能没有指定原因,因此在这些情况下,我们的示例错误处理程序会回退到显示标准 message 属性。

请注意,由于此代码不会进行身份验证,因此您只能将其用于获取公开 Feed。

身份验证

JavaScript 客户端库可以用在两种模式下。如果您正在编写小工具,则该小工具会使用 OAuth 代理功能进行身份验证。如果是通过独立的 JavaScript 应用进行访问,那么该应用会使用 AuthSub 身份验证系统。 如需了解身份验证,请参阅 Google 数据 API 身份验证概览文档。本部分的其余部分假设您熟悉此系统的工作原理。

在通过本文档中提供的示例代码使用身份验证之前,请将 Feed 网址从“公开”更改为“私有”:

var feedUrl = "http://www.google.com/calendar/feeds/liz@gmail.com/private/full";

使用 AuthSub 在 Web 客户端中进行身份验证

Google 的“AuthSub for JavaScript”授权系统不再可用。

我们建议您针对客户端应用使用 OAuth 2.0

使用 OAuth 代理的小工具中的身份验证

下面简要介绍了在小工具身份验证过程中所发生的情况:

  1. 您的小工具是第一次加载,并尝试使用某个 Google 数据 API 访问用户数据。
  2. 由于用户尚未授予其数据的访问权限,因此请求失败。 响应对象包含 OAuth 审批页面的网址(位于 response.oauthApprovalUrl 中)。您的小工具应提供一种方法来使用该网址启动新窗口。
  3. 在审批页面上,用户选择授予/拒绝访问您的小工具的权限。如果成功,系统会将用户转到您指定的 oauth_callback 页面。为了提供最佳用户体验,请使用 http://oauth.gmodules.com/gadgets/oauthcallback
  4. 接下来,用户会关闭弹出式窗口。为了帮助通知您的小工具用户已给予批准,我们提供了弹出式窗口处理程序,您可以使用它来检测审批关闭窗口。或者,您的小工具可以显示一个链接(例如“我已批准的访问权限”),以供用户在此窗口关闭后手动点击。
  5. 您的小工具通过重新请求用户的数据来尝试再次访问 Google Data API。此尝试成功。
  6. 您的小工具已经过身份验证,可以开始正常运行。

在小工具的 <ModulePrefs> 部分添加 <OAuth> 元素:

<ModulePrefs>
...
<OAuth>
  <Service name="google">
    <Access url="https://www.google.com/accounts/OAuthGetAccessToken" method="GET" /> 
    <Request url="https://www.google.com/accounts/OAuthGetRequestToken?
                  scope=http://www.blogger.com/feeds/%20http://www.google.com/calendar/feeds/" method="GET" /> 
    <Authorization url="https://www.google.com/accounts/OAuthAuthorizeToken?
                        oauth_callback=http://oauth.gmodules.com/gadgets/oauthcallback" /> 
  </Service>
</OAuth>
...
</ModulePrefs>

在本部分中,更改以下查询参数:

  • scope

    请求网址中的一个必需参数。您的小工具将只能访问此参数中使用的scope的数据。 在此示例中,这个小工具将访问您的 Blogger 和日历数据。小工具可以请求单个范围或多个范围的数据(如此示例所示)。

  • oauth_callback

    授权网址中的可选参数。用户批准访问其数据后,OAuth 审批页面会重定向到此网址。 您可以选择省略此参数,将其设置为您自己的“已批准页面”,或者最好使用 http://oauth.gmodules.com/gadgets/oauthcallback。后者可在用户首次安装您的小工具时提供最佳用户体验。该网页提供一段 JavaScript 代码,用于自动关闭弹出式窗口。

接下来,在小工具的 <Content> 部分中加载 JavaScript 客户端库。修改前面示例中的 setupMyService() 函数以调用服务对象的 useOAuth() 方法。这会告知小工具使用 OAuth 代理进行身份验证,而不是使用 AuthSub。使用此模板即可开始使用:

<Content type="html">
<![CDATA[
  ...
  <script src="https://www.google.com/jsapi"></script>
  <script type="text/javascript">
    var myService = null;
    
    function setupMyService() {
      myService = new google.gdata.calendar.CalendarService('exampleCo-exampleApp-1');
      myService.useOAuth('google');
      fetchData();
    }
    
    function initGadget() {
      google.load('gdata', '2.x');
      google.setOnLoadCallback(setupMyService);
    }

    function fetchData() {            
      var callback = function(response) {
        if (response.oauthApprovalUrl) {
        
          // TODO: Display "Sign in" link (response.oauthApprovalUrl contains the URL) 
          
        } else if (response.feed) {
        
          // TODO: show results
          
        } else {
        
          // TODO: handle the error
          
        }
      };

      myService.getEventsFeed('http://www.google.com/calendar/feeds/default/public/full', callback, callback);
    }
    
    gadgets.util.registerOnLoadHandler(initGadget);
  </script>
  ...
]]> 
</Content>

请注意,对 google.accounts.user.login(scope) 的调用已移除。代理会为您处理身份验证。

有关编写 Google Data API 小工具的详细信息,包括 fetchData() 应包含的内容的详细信息,请参阅我们关于创建 Google 数据小工具的文章或查看完整的编写 OAuth 小工具文档。

插入新项

如需创建新的日历活动,请继续修改前面的示例,修改 handleMyFeed() 函数的末尾以调用新函数:

function handleMyFeed(myResultsFeedRoot) {
  alert("This feed's title is: " + myResultsFeedRoot.feed.getTitle().getText());
  insertIntoMyFeed(myResultsFeedRoot);
}

在新函数中,首先使用 CalendarEventEntry 构造函数创建新条目。然后插入该条目,为回调提供在插入完成后调用的回调。

function insertIntoMyFeed(feedRoot) {
  var newEntry = new google.gdata.calendar.CalendarEventEntry({
      authors: [{
        name: "Elizabeth Bennet",
        email: "liz@gmail.com"
      }],
      title: {
        type: 'text', 
        text: 'Tennis with Darcy'
      },
      content: {
        type: 'text', 
        text: 'Meet for a quick lesson'
      },
      locations: [{
        rel: "g.event",
        label: "Event location",
        valueString: "Netherfield Park tennis court"
      }],
      times: [{
        startTime: google.gdata.DateTime.fromIso8601("2007-09-23T18:00:00.000Z"),
        endTime: google.gdata.DateTime.fromIso8601("2007-09-23T19:00:00.000Z")
      }]
  });
  feedRoot.feed.insertEntry(newEntry, handleMyInsertedEntry, handleError);
}

请注意,构造函数中使用的每个对象属性的名称都与用于属性的 setter 方法的名称一致。(例如,不与对应的 JSON 字段名称匹配。)

另请注意,您不能仅仅为 startTimeendTime 提供 ISO 8601 日期和时间字符串;必须先通过 fromIso8601() 方法运行此类字符串。

该服务以 entryRoot 对象的形式返回所插入条目的副本,并将该对象传递给回调函数:

function handleMyInsertedEntry(insertedEntryRoot) {
  alert("Entry inserted. The title is: " + insertedEntryRoot.entry.getTitle().getText());
  alert("The timestamp is: " + insertedEntryRoot.entry.getTimes()[0].startTime);
}

请求特定条目

如需请求特定条目,请先修改 handleMyInsertedEntry() 函数以调用新的条目请求函数:

function handleMyInsertedEntry(insertedEntryRoot) {
  alert("Entry inserted. The title is: " + insertedEntryRoot.entry.getTitle().getText());
  alert("The timestamp is: " + insertedEntryRoot.entry.getTimes()[0].startTime);
  requestMySpecificEntry(insertedEntryRoot.entry.getSelfLink().getHref());
}

通过以下代码,您可以请求在上一个示例中插入的特定条目。

在本系列示例中,由于条目已返回所插入的条目,因此不必检索该条目;但只要您知道条目的 URI,就可以使用相同的方法。

function requestMySpecificEntry(entryURI) {
  myService.getEventsEntry(entryURI, handleMySpecificEntry, handleError);
}

function handleMySpecificEntry(retrievedEntryRoot) {
  myEntryRoot = retrievedEntryRoot; // Global variable for later use
  alert("This entry's title is: " + retrievedEntryRoot.entry.getTitle().getText());
}

此示例基本上与 getEventsFeed() 示例相同,只是我们调用了服务的 getEventEntry() 方法来获取特定条目,而 URI 则略有不同 - 它使用“default”来引用经过身份验证的用户的主日历,并且它末尾有一个条目 ID。

此外,我们还需要稍后使用检索到的条目,因此需要将其复制到全局变量中。

搜索条目

如需执行全文搜索,请先修改 handleMySpecificEntry() 函数以调用新的搜索函数:

function handleMySpecificEntry(retrievedEntryRoot) {
  myEntryRoot = retrievedEntryRoot; // Global variable for later use
  alert("This entry's title is: " + retrievedEntryRoot.entry.getTitle().getText());
  searchMyFeed();
}

然后,若要从搜索中检索第一个匹配项,请使用以下代码:

function searchMyFeed() {
  var myQuery = new google.gdata.calendar.CalendarEventQuery(feedUrl);
  myQuery.setFullTextQuery("Tennis");
  myQuery.setMaxResults(10);
  myService.getEventsFeed(myQuery, handleMyQueryResults, handleError);
}

function handleMyQueryResults(myResultsFeedRoot) {
  if (myResultsFeedRoot.feed.getEntries()[0]) {
    alert("The first search-match entry's title is: " + myResultsFeedRoot.feed.getEntries()[0].getTitle().getText());
  }
  else {
    alert("There are no entries that match the search query.");
  }
}

更新商品

如需更新现有项,请先在 handleMyQueryResults() 末尾添加一行代码来调用新的更新函数:

  updateMyEntry();

然后使用以下代码。在此示例中,我们将之前检索到的条目(包含在前面示例中的名为 myEntryRoot 的全局对象中)的标题从其旧文本(“带 Darcy 的网球”)更改为“重要会议”。

function updateMyEntry() {
  myEntryRoot.entry.getTitle().setText("Important meeting");
  myEntryRoot.entry.updateEntry(handleMyUpdatedEntry, handleError);
}

function handleMyUpdatedEntry(updatedEntryRoot) {
  alert("Entry updated. The new title is: " + updatedEntryRoot.entry.getTitle().getText());
}

与所有日历方法一样,updateEntry() 方法会自动确定要在更新条目时使用的正确修改 URI,因此您无需明确提供该 URI。

删除商品

如需删除更新后的条目,请先向 handleMyUpdatedEntry() 添加一行代码:

 deleteMyEntry(updatedEntryRoot);

然后使用以下代码:

function deleteMyEntry(updatedEntryRoot) {
  updatedEntryRoot.entry.deleteEntry(handleMyDeletedEntry, handleError);
}

function handleMyDeletedEntry() {
  alert("Entry deleted");
}

同样,deleteEntry() 方法会自动确定用于删除条目的正确修改 URI。

请注意,系统不会返回任何条目。如果该回调函数被调用,就表示删除成功;如果删除失败,deleteEntry() 会调用 handleError(),而不是调用 handleMyDeletedEntry()

使用 ETag

注意:ETag 只能与运行 Google Data Protocol v2.0 的服务搭配使用。

简介

Google Data JavaScript 客户端版本 2 支持 ETag。ETag 是用于指定特定条目特定版本的标识符,在以下两种情况下尤为重要:

  • 执行“条件检索”,即客户端请求条目,而服务器仅在条目自客户端上次请求以来发生了更改的情况下发送条目。
  • 确保多个客户端不会意外覆盖彼此的更改。如果客户端为条目指定了旧 ETag,则 Data API 通过更新和删除操作就会失败。

ETag 有两种:弱和强。弱 ETag 始终以 W/ 开头,例如:W/"D08FQn8-eil7ImA9WxZbFEw"。弱 ETag 不能保证会在条目发生更改时发生更改,因此 HTTP 仅允许用于有条件检索。强 ETag 可用于识别特定条目的特定版本,既可用于条件检索,也可用于更新或删除期间,以避免覆盖其他客户端的更改。正因为如此,该客户端库不允许您在更新或删除请求中发送弱 ETag。

ETag 可在服务器响应中的两个位置找到:

  • ETag HTTP 标头中。
  • 在 Feed/条目中,作为 gd:etag 属性。

如果服务支持版本 2,则每个 Feed 和条目对象都将具有 getEtag() 方法,用于检索 ETag 的值。

JavaScript 客户端支持两种在请求中添加 ETag。第一个是新的 opt_params 对象。客户端库版本 2 中的所有 get/update/insert 函数都有一个新的 opt_params 参数。该对象用于在发出请求时指定可选参数。目前,'etag' 是唯一受支持的可选参数(但将来可能会引入其他参数)。例如,您可以在 GET 请求中添加如下所示的 ETag:

var opt_params = {};
opt_params['etag'] = 'ETAG GOES HERE';
service.getFeed(uri, successHandler, errorHandler, opt_params);

您还可以通过对 Feed/条目调用 setEtag() 方法,将 ETag 直接添加到 Feed 或条目对象中。

您可以参阅 GData 协议参考,详细了解 ETag。

使用 ETag 检索数据

ETag 有助于在检索数据时减少带宽和执行时间。使用 If-None-Match header: 的 GET 请求中可以包含 ETag

If-None-Match: ETAG GOES HERE

如果 ETag 与当前版本的 Feed 或条目匹配,则服务器会返回 304 NOT MODIFIED 响应和空正文。否则,服务器会返回 200 OK 响应以及 Feed 或条目数据。

您可以在 JavaScript 客户端中使用 ETag,方法是在发出请求时添加 'etag' 参数:

var etag = feed.getEtag(); // Feed loaded from a previous request
var opt_params = {};
opt_params['etag'] = etag;
service.getFeed(feedUrl, successHandler, errorHandler, opt_params);

条件检索同时适用于强 ETag 和弱 ETag。如果 ETag 匹配,系统将使用 304 响应调用错误处理程序:

function successHandler(feedRoot) {
  // 200 response
  // Update UI to display updates
}

function errorHandler(errorObj) {
  if (errorObj.cause.getStatus() == 304) {
    // 304 response, do nothing
  }
  // otherwise the response is some other error
}

请参阅使用 Blogger 按条件检索示例,了解在 JavaScript 客户端中使用 ETag 的更实际示例。此示例会每隔 5 秒轮询一次 Blogger,查找博客的更新。如有更改,此示例会更新帖子列表。

使用 ETag 更新和删除数据

在更新/删除请求中使用 ETag 可确保多个客户端不会无意中覆盖彼此的更改。在本例中,If-Match 标头中包含一个 ETag:

If-Match: ETAG GOES HERE

如果请求中的 ETag 与服务器上的 ETag 匹配,则更新/删除成功。但是,如果 ETag 不匹配,则表示条目已更改,且更新/删除失败。在这种情况下,应用应请求新的数据实例,然后再次尝试更新/删除。

在某些情况下,无论对条目做出何种其他更改,您都可能需要强制进行更改。为此,您可以将 * 传递给 If-Match 标头:

If-Match: *

请注意,这会覆盖其他客户端所做的更改,因此请务必谨慎使用。

您只能更新/删除具有强 ETag 的条目。指定弱 ETag 将导致错误。为了防止出现这种情况,JavaScript 客户端不会在更新和删除请求上设置较弱的 ETag。

ETag 的使用方式与条件检索相同:

function updateData(entry, service) {
  var etag = entry.getEtag();
  var opt_params = {};
  opt_params['etag'] = etag; // Or use '*' to force an update.
  service.updateEntry(successHandler, errorHandler, opt_params);
}

function successHandler(response) {
  // Successful update
}

function errorHandler(errorObj) {
  // ERROR - Update failed. Could be due to an ETag mismatch, but check the
  // error message to make sure. An ETag error will be in the format:
  // Mismatch: etags = ["Qnc-fTVSLyp7ImA9WxJbFEsDRAw."], version = [1249675665358000]
}

在进行更新时,可以在两个位置指定 ETag:

  1. 在条目本身中,使用 getEtag()setEtag() 方法。
  2. 在标头中,使用 opt_params 对象(如上所示)。

从上一个 GET 请求加载的条目已具有 ETag 字段。因此,在 opt_params 对象中指定相同的 ETag 是多余的。如果条目正文和 opt_params 中均指定了 ETag,则以 opt_params 中的 ETag 为准。这可能有点令人困惑,因此,如果您遇到条件更新方面的问题,请务必查看条目和 opt_params 对象中的 ETag。

为了简化操作,google.gdata.Entry 类也有自己的 updateEntry()deleteEntry() 方法。如果条目类已有 ETag,则无需将其添加到请求;客户端库会自动为您执行此操作。例如:

// entry was loaded from a previous request.  No need to specify
// an ETag in opt_params here, it is added automatically.
entry.deleteEntry(successHandler, errorHandler);

这样一来,您就可以轻松使用 ETag,而不必担心其设置是否有误。但是,如果要使用 '*' 强制更新,则必须始终使用 'etag' = '*' 添加 opt_params 对象。

您可以在 Google 通讯录的条件更新中查看有条件的更新。该示例首先会创建一个测试联系人群组,其中将创建此示例使用的所有数据。使用示例后,您可以随时删除此联系人群组。然后,此示例会使用联系人群组中的内容加载两个 iframe。您可以在一个 iframe 中进行更新,看看该设置对另一个 iframe 中的更新有何影响。如需详细了解如何使用,请参阅示例。

示例

参考

如需了解客户端库提供的类和方法,请参阅 JavaScript 客户端库 API 参考文档(采用 JSdoc 格式)。

返回页首