[JavaScript General] XMLHttpRequest する関数を Promise を返すように修正するチュートリアルをやってみた

Promise を利用すれば、非同期処理の書き方を統一できることを学んだ。

JavaScript Promise 入門 | deadwood

こちらを参考にチュートリアルをやってみた。

JavaScript Promiseの本

'use strict';
require('babel-polyfill');
/**
 * @param {String} URL
 * @return {Promise}
 */
function getURL(URL) {
  return new Promise((resolve, reject) => {
    let req = new XMLHttpRequest();
    req.open('GET', URL, true);
    req.onload = function() {
      if (req.status === 200) {
        resolve(req.responseText);
      } else {
        reject(new Error(req.statusText));
      }
    };
    req.onerror = function() {
      reject(new Error(req.statusText));
    };
    req.send();
  });
}
let URL = 'http://httpbin.org/get';
getURL(URL).then(function onFulfilled(value) {
  console.log(value);
}).catch(function onRejected(error) {
  console.error(error);
});

JavaScriptの入門書 #jsprimer

モダンな JS かつ説明が丁寧でとてもありがたい。
JS 力がなさ過ぎて onclick で動かせなかった。

'use strict';
require('babel-polyfill');
let el = document.getElementById('btn');
el.addEventListener('click', function() {
  main();
});
/**
 * Main & console error.
 */
function main() {
  const userId = document.getElementById('userId').value;
  getUserInfo(userId)
    .then((userInfo) => createView(userInfo))
    .then((view) => displayView(view))
    .catch((error) => {
      console.error(`エラーが発生しました (${error})`);
    });
}
/**
 * Get User information from Github.
 * @param {String} userId
 * @return {Promise}
 */
function getUserInfo(userId) {
  return new Promise((resolve, reject) => {
    const request = new XMLHttpRequest();
    request.open('GET', `https://api.github.com/users/${userId}`);
    request.addEventListener('load', (event) => {
      if (event.target.status !== 200) {
        reject(new Error(`${event.target.status}: ${event.target.statusText}`));
      }
      const userInfo = JSON.parse(event.target.responseText);
      resolve(userInfo);
    });
    request.addEventListener('error', () => {
      reject(new Error('Network Error'));
    });
    request.send();
  });
}
/**
 * Create a view at HTML tags.
 * @param {Object} userInfo
 * @return {String}
 */
function createView(userInfo) {
  /* eslint-disable no-unused-vars */
  return escapeHTML`
  <h4>${userInfo.name} (@${userInfo.login})</h4>
  <img src="${userInfo.avatar_url}" alt="${userInfo.login}" height="100">
  <dl>
    <dt>Location</dt>
    <dd>${userInfo.location}</dd>
    <dt>Repositries</dt>
    <dd>${userInfo.public_repos}</dd>
  </dl>
  `;
}
/**
 * Display a view to #result in HTML.
 * @param {String} view
 */
function displayView(view) {
  const result = document.getElementById('result');
  result.innerHTML = view;
}
/**
 * Escape HTML special characters.
 * @param {String} str
 * @return {String}
 */
function escapeSpecialChars(str) {
  return str
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
}
/**
 * Escape HTML tags from strings.
 * @param {Strings} strings
 * @return {String}
 */
function escapeHTML(strings, ...values) {
  return strings.map((part, i) => {
    const value = values[i];
    if (value) {
      if (typeof value === 'string') {
        return part + escapeSpecialChars(value);
      } else {
        return part + String(value);
      }
    } else {
      return part;
    }
  }).join('');
}

Promise のユースケース代表例の XMLHttpRequest が理解しやすかった。
XHR -> HTML組み立て -> View の流れがイメージできるようになって助かった。
他にはどんなユースケースがあるのか知りたい。
Promise のテストについては、今の理解度では足りなかったので今後の課題とする。