この翻訳は不完全です。英語から この記事を翻訳 してください。

これまで説明してきた API はブラウザに組み込まれていましたが、すべての API がそうというわけではありません。Google Maps・Twitter・Facebook・PayPal などの大規模なサイトやサービスの多くは開発者がそれらのデータ (ブログに Twitter のストリームを表示するなど) やサービス (ユーザのログインに Facebook ログインを利用するなど) を利用できるように API を提供しています。この記事ではブラウザ API とサードパーティ API の違いを見て、後者の典型的な使い方について説明します。

前提知識: JavaScript の基礎 (JavaScript の第一歩, JavaScript の構成要素, JavaScript オブジェクト入門 をご覧ください),クライアントサイド API の基礎
到達目標: サードパーティ API の仕組み、それらを利用して Web サイトを強化する方法を学習する

サードパーティAPIとは?

サードパーティ API は、サードパーティ (通常は Facebook、Twitter、Google などの企業) が提供する API で、JavaScript を介して機能にアクセスしてサイトで使用することができます。最もわかりやすい例の1つとして、マッピング API を使用してページにカスタムマップを表示することがあります。

Simple Mapquest API の例を参考に、サードパーティ API とブラウザ API の違いを説明します。

注意: 一度にすべてのコード例を取得したい場合があります。その場合は、各セクションで必要なサンプルファイルをレポジトリで検索するだけで済みます。

それらはサードパーティのサーバにあります

 

ブラウザ API はブラウザに組み込まれており、すぐに JavaScript からアクセスできます。たとえば、紹介記事で見たWeb Audio API は、ネイティブの AudioContext オブジェクトを使ってアクセスします。例えば:

const audioCtx = new AudioContext();
  ...
const audioElement = document.querySelector('audio');
  ...
const audioSource = audioCtx.createMediaElementSource(audioElement);
// etc.

一方、サードパーティの API はサードパーティのサーバにあります。JavaScript からこれらにアクセスするには、まず API 機能に接続してページで利用できるようにする必要があります。 これは通常、Mapquest の例で見られるように、<script> 要素を介してサーバ上で利用可能なJavaScriptライブラリへの最初のリンクを含めます。

<script src="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.js"></script>
<link type="text/css" rel="stylesheet" href="https://api.mqcdn.com/sdk/mapquest-js/v1.3.2/mapquest.css"/>

そのライブラリで利用可能なオブジェクトを使い始めることができます。例えば:

var L;

var map = L.mapquest.map('map', {
  center: [53.480759, -2.242631],
  layers: L.mapquest.tileLayer('map'),
  zoom: 12
});

ここでは、マップ情報を格納するための変数を作成し、次に mapquest.map() メソッドを使用して新しいマップを作成します。このメソッドは、必要な <div> 要素のIDを受け取ります。('map') で地図を表示し、表示したい特定の地図の詳細を含む options オブジェクトを表示します。この場合は、地図の中心座標、表示する map 型の地図レイヤ (mapquest.tileLayer() メソッドを使用して作成)、およびデフォルトのズームレベルを指定します。

これが、Mapquest API が単純な地図を描くために必要なすべての情報です。接続しているサーバは、表示されている地域の正しい地図タイルを表示するなど、複雑なものをすべて処理します。

メモ: API の中には、機能へのアクセスをわずかに異なる方法で処理するものがあり、開発者はデータを取得するために特定の URL パターンに対して HTTP リクエストを行う必要があります。これらは RESTful API と呼ばれ、後で例が出てきます

通常は API キーが必要です

最初の記事で説明したように、ブラウザ API のセキュリティは許可プロンプトによって処理される傾向があります。これらの目的は、ユーザが訪問した Web サイトで何が起こっているのかをユーザ自身が認識できるようにし、悪意のある方法で API を使用している人の被害にあう可能性を低くすることです。

サードパーティの API には、少し異なる権限システムがあります。開発者が API 機能にアクセスできるようにするために開発者キーを使用する傾向があります。

Mapquest API の例には、次のような行があります。

L.mapquest.key = 'YOUR-API-KEY-HERE';

この行では、アプリケーションで使用する API キーまたは開発者キーを指定します。アプリケーションの開発者は、キーを取得して API の機能へのアクセス許可を得るためにコードに含める必要があります。この例では、プレースホルダを用意しました。

メモ: 独自の例を作成するときは、プレースホルダの代わりに独自の API キーを使用します。

他の API では、少し異なる方法でキーを含める必要があるかもしれませんが、ほとんどのパターンは比較的似ています。

キーを要求することで、API プロバイダは API のユーザに自分のアクションに対する責任を持たせることができます。開発者がキーを登録すると、それらは API プロバイダに認識され、彼らが API に悪意のあることをし始めたらアクション  (たとえば、人々の位置を追跡したり、APIを機能させないために大量のリクエストでAPIをスパムしようとするなど) を取ることができます。最も簡単なアクションは、単にそれらの API 特権を取り消すことです。

Mapquest の例を拡張する

API の他の機能の使用方法を示すために、Mapquest の例にさらに機能を追加しましょう。

  1. To start this section, make yourself a copy of the mapquest starter file, in a new directory. If you've already cloned the examples repository, you'll already have a copy of this file, which you can find in the javascript/apis/third-party-apis/mapquest directory.

  2. Next, you need to go to the Mapquest developer site, create an account, and then create a developer key to use with your example. (At the time of writing, it was called a "consumer key" on the site, and the key creation process also asked for an optional "callback URL". You don't need to fill in a URL here: just leave it blank.)

  3. Open up your starting file, and replace the API key placeholder with your key.

地図の種類を変更する

There are a number of different types of map that can be shown with the Mapquest API. To do this, find the following line:

layers: L.mapquest.tileLayer('map')

Try changing 'map' to 'hybrid' to show a hybrid-style map. Try some other values too. The tileLayer reference page shows the different available options, plus a lot more information.

さまざまなコントロールを追加する

The map has a number of different controls available; by default it just shows a zoom control. You can expand the controls available using the map.addControl() method; add this to your code, inside the window.onload handler:

map.addControl(L.mapquest.control());

The mapquest.control() method just creates a simple full-featured control set, and it is placed in the top-right hand corner by default. You can adjust the position by specifying an options object as a parameter for the control containing a position property, the value of which is a string speciying a position for the control. Try this, for example:

map.addControl(L.mapquest.control({ position: 'bottomright' }));

There are other types of control available, for example mapquest.searchControl() and mapquest.satelliteControl(), and some are quite complex and powerful. Have a play around and see what you can come up with.

カスタムマーカーを追加する

Adding a marker (icon) at a certain point on the map is easy — you just use the L.marker() method (which seems to be documented in the related Leaflet.js docs). Add the following code to your example, again inside window.onload:

L.marker([53.480759, -2.242631], {
  icon: L.mapquest.icons.marker({
    primaryColor: '#22407F',
    secondaryColor: '#3B5998',
    shadow: true,
    size: 'md',
    symbol: 'A'
  })
})
.bindPopup('This is Manchester!')
.addTo(map);

As you can see, this at its simplest takes two parameters, an array containing the coordinates at which to display the marker, and an options object containing an icon property that defines the icon to display at that point.

The icon is defined using an mapquest.icons.marker() method, which as you can see contains information such as color and size of marker.

Onto the end of the first method call we chain .bindPopup('This is Manchester!'), which defines content to display when the marker is clicked.

Finally, we chain .addTo(map) to the end of the chain to actually add the marker to the map.

Have a play with the other options shown in the documentation and see what you can come up with! Mapquest provides some pretty advanced functionality, such as directions, searching, etc.

Note: If you have trouble getting the example to work, check your code against our finished version — see expanded-example.html.

Google マップはどうですか?

Google Maps is arguably the most popular maps API, so why didn't we use it for our maps example? We did create an example to show how to use it, but in the end we went with Mapquest for a couple of reasons:

  • It is much easier to get started with. For Google APIs in general, you need to create a Google account and log into the Google Cloud Platform Console to create API keys, etc., and the process is fairly complex. For the Google Maps API in particular, you need to provide a credit card for billing purposes (although basic usage is free), which we didn't think was acceptable for a basic tutorial.
  • We wanted to show that there are other alternatives available.

RESTful API — NYTimes の例

Now let's look at another API example — the New York Times API. This API allows you to retrieve New York Times news story information and display it on your site. This type of API is known as a RESTful API — instead of getting data using the features of a JavaScript library like we did with Mapquest, we get data by making HTTP requests to specific URLs, with data like search terms and other properties encoded in the URL (often as URL parameters). This is a common pattern you'll encounter with APIs.

An approach for using third-party APIs

Below we'll take you through an exercise to show you how to use the NYTimes API, which also provides a more general set of steps to follow that you can use as an approach for working with new APIs.

Find the documentation

When you want to use a third party API, it is essential to find out where the documentation is, so you can find out what features the API has, how you use them, etc. The New York Times API documentation is at https://developer.nytimes.com/.

Get a developer key

Most APIs require you to use some kind of developer key, for reasons of security and accountability. To sign up for an NYTimes API key, following the instructions at https://developer.nytimes.com/get-started.

  1. Let's request a key for the Article Search API — create a new app, selecting this as the API you want to use (fill in a name and description, toggle the switch under the "Article Search API" to the on position, and then click "Create").

  2. Get the API key from the resulting page.

  3. Now, to start the example off, make copies of nytimes_start.html and nytimes.css in a new directory on your computer. If you've already cloned the examples repository, you'll already have a copy of these files, which you can find in the javascript/apis/third-party-apis/nytimes directory. Initially the <script> element contains a number of variables needed for the setup of the example; below we'll fill in the required functionality.

The app will end up allowing you to type in a search term and optional start and end dates, which it will then use to query the Article Search API and display the search results.

Connect the API to your app

First, you'll need to make a connection between the API and your app. In the case of this API, you need to include the API key as a get parameter every time you request data from the service at the correct URL.

  1. Find the following line:

    var key = ' ... ';
  • Replace the existing API key with the actual API key you got in the previous section.

  • Add the following line to your JavaScript, below the "// Event listeners to control the functionality" comment. This runs a function called submitSearch() when the form is submitted (the button is pressed).

    searchForm.addEventListener('submit', submitSearch);
  •  
  • Now add the submitSearch() and fetchResults() function definitions, below the previous line:

    function submitSearch(e) {
      pageNumber = 0;
      fetchResults(e);
    }
    
    function fetchResults(e) {
      // Use preventDefault() to stop the form submitting
      e.preventDefault();
    
      // Assemble the full URL
      url = baseURL + '?api-key=' + key + '&page=' + pageNumber + '&q=' + searchTerm.value + '&fq=document_type:("article")';
    
      if(startDate.value !== '') {
        url += '&begin_date=' + startDate.value;
      };
    
      if(endDate.value !== '') {
        url += '&end_date=' + endDate.value;
      };
    
    }
  1.  

submitSearch() sets the page number back to 0 to begin with, then calls fetchResults(). This first calls preventDefault() on the event object, to stop the form actually submitting (which would break the example). Next, we use some string manipulation to assemble the full URL that we will make the request to. We start off by assembling the parts we deem as mandatory for this demo:

  • The base URL (taken from the baseURL variable).
  • The API key, which has to be specified in the api-key URL parameter (the value is taken from the key variable).
  • The page number, which has to be specified in the page URL parameter (the value is taken from the pageNumber variable).
  • The search term, which has to be specified in the q URL parameter (the value is taken from the value of the searchTerm text <input>).
  • The document type to return results for, as specified in an expression passed in via the fq URL parameter. In this case, we want to return articles.

Next, we use a couple of if() statements to check whether the startDate and endDate <input>s have had values filled in on them. If they do, we append their values to the URL, specified in begin_date and end_date URL parameters respectively.

So, a complete URL would end up looking something like this:

https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=YOUR-API-KEY-HERE&page=0&q=cats
&fq=document_type:("article")&begin_date=20170301&end_date=20170312

Note: You can find more details of what URL parameters can be included at the NYTimes developer docs.

Note: The example has rudimentary form data validation — the search term field has to be filled in before the form can be submitted (achieved using the required attribute), and the date fields have pattern attributes specified, which means they won't submit unless their values consist of 8 numbers (pattern="[0-9]{8}"). See Form data validation for more details on how these work.

Requesting data from the API

Now we've constructed our URL, let's make a request to it. We'll do this using the Fetch API.

Add the following code block inside the fetchResults() function, just above the closing curly brace:

// Use fetch() to make the request to the API
fetch(url).then(function(result) {
  return result.json();
}).then(function(json) {
  displayResults(json);
});

Here we run the request by passing our url variable to fetch(), convert the response body to JSON using the json() function, then pass the resulting JSON to the displayResults() function so the data can be displayed in our UI.

Displaying the data

OK, let's look at how we'll display the data. Add the following function below your fetchResults() function.

function displayResults(json) {
  while (section.firstChild) {
      section.removeChild(section.firstChild);
  }

  var articles = json.response.docs;

  if(articles.length === 10) {
    nav.style.display = 'block';
  } else {
    nav.style.display = 'none';
  }

  if(articles.length === 0) {
    var para = document.createElement('p');
    para.textContent = 'No results returned.'
    section.appendChild(para);
  } else {
    for(var i = 0; i < articles.length; i++) {
      var article = document.createElement('article');
      var heading = document.createElement('h2');
      var link = document.createElement('a');
      var img = document.createElement('img');
      var para1 = document.createElement('p');
      var para2 = document.createElement('p');
      var clearfix = document.createElement('div');

      var current = articles[i];
      console.log(current);

      link.href = current.web_url;
      link.textContent = current.headline.main;
      para1.textContent = current.snippet;
      para2.textContent = 'Keywords: ';
      for(var j = 0; j < current.keywords.length; j++) {
        var span = document.createElement('span');
        span.textContent += current.keywords[j].value + ' ';
        para2.appendChild(span);
      }

      if(current.multimedia.length > 0) {
        img.src = 'http://www.nytimes.com/' + current.multimedia[0].url;
        img.alt = current.headline.main;
      }

      clearfix.setAttribute('class','clearfix');

      article.appendChild(heading);
      heading.appendChild(link);
      article.appendChild(img);
      article.appendChild(para1);
      article.appendChild(para2);
      article.appendChild(clearfix);
      section.appendChild(article);
    }
  }
}

There's a lot of code here; let's explain it step by step:

  • The while loop is a common pattern used to delete all of the contents of a DOM element, in this case, the <section> element. We keep checking to see if the <section> has a first child, and if it does, we remove the first child. The loop ends when <section> no longer has any children.
  • Next, we set the articles variable to equal json.response.docs — this is the array holding all the objects that represent the articles returned by the search. This is done purely to make the following code a bit simpler.
  • The first if() block checks to see if 10 articles are returned (the API returns up to 10 articles at a time.) If so, we display the <nav> that contains the Previous 10/Next 10 pagination buttons. If less than 10 articles are returned, they will all fit on one page, so we don't need to show the pagination buttons. We will wire up the pagination functionality in the next section.
  • The next if() block checks to see if no articles are returned. If so, we don't try to display any — we create a <p> containing the text "No results returned." and insert it into the.<section>
  • If some articles are returned, we, first of all, create all the elements that we want to use to display each news story, insert the right contents into each one, and then insert them into the DOM at the appropriate places. To work out which properties in the article objects contained the right data to show, we consulted the Article Search API reference (see NYTimes APIs). Most of these operations are fairly obvious, but a few are worth calling out:
    • We used a for loop (for(var j = 0; j < current.keywords.length; j++) { ... } ) to loop through all the keywords associated with each article, and insert each one inside its own <span>, inside a <p>. This was done to make it easy to style each one.
    • We used an if() block (if(current.multimedia.length > 0) { ... }) to check whether each article has any images associated with it (some stories don't.) We display the first image only if it exists (otherwise an error would be thrown).
    • We gave our <div> element a class of "clearfix", so we can easily apply clearing to it.

Wiring up the pagination buttons

To make the pagination buttons work, we will increment (or decrement) the value of the pageNumber variable, and then re-rerun the fetch request with the new value included in the page URL parameter. This works because the NYTimes API only returns 10 results at a time — if more than 10 results are available, it will return the first 10 (0-9) if the page URL parameter is set to 0 (or not included at all — 0 is the default value), the next 10 (10-19) if it is set to 1, and so on.

This allows us to write a simplistic pagination function easily.

  1. Below the existing addEventListener() call, add these two new ones, which cause the nextPage() and previousPage() functions to be invoked when the relevant buttons are clicked:

    nextBtn.addEventListener('click', nextPage);
    previousBtn.addEventListener('click', previousPage);
  •  
  • Below your previous addition, let's define the two functions — add this code now:

    function nextPage(e) {
      pageNumber++;
      fetchResults(e);
    };
    
    function previousPage(e) {
      if(pageNumber > 0) {
        pageNumber--;
      } else {
        return;
      }
      fetchResults(e);
    };
  1. The first function is simple — we increment the pageNumber variable, then run the fetchResults() function again to display the next page's results.

    The second function works nearly exactly the same way in reverse, but we also have to take the extra step of checking that pageNumber is not already zero before decrementing it — if the fetch request runs with a minus page URL parameter, it could cause errors. If the pageNumber is already 0, we simply return out of the function, to avoid wasting processing power (If we are already at the first page, we don't need to load the same results again).

YouTube の例

We also built another example for you to study and learn from — see our YouTube video search example. This uses two related APIs:

This example is interesting because it shows two related third-party APIs being used together to build an app. The first one is a RESTful API, while the second one works more like Mapquest (with API-specific methods, etc.). It is worth noting however that both of the APIs require a JavaScript library to be applied to the page. The RESTful API has functions available to handle making the HTTP requests and returning the results.

We are not going to say too much more about this example in the article — the source code has detailed comments inserted inside it to explain how it works. You'll still need to get an API key and insert it into the code to get it working, like with the other examples.

 

まとめ

この記事では、サードパーティ API を使用して Web サイトに機能を追加するための便利な方法を紹介しました。

このモジュール

ドキュメントのタグと貢献者

このページの貢献者: silverskyvicto, mdnwebdocs-bot, yagochi
最終更新者: silverskyvicto,