saiko memo

じぶん用の技術メモ

try ... catch についての学習メモ

JavaScripttry ... catchについて今まで使う機会がなく、何も知らなかったので勉強してみたメモ。

結論から言うと、エラーが発生した場合でも処理を停止させないという特徴があるようです。

// 未定義の変数iによりエラーが発生する

// 通常の処理
const a = 1;
const b = a * i; // コンソールにエラー出力
console.log( 'hoge' ); // この行は実行されない

// try ... catchによる処理
const a = 1;
try {
  const b = a * i; // 例外が発生し、catchブロックに処理が移る
} catch (e) {
  console.error( e ); // エラー内容を引数で受取り、エラーを出力
}
console.log('hoge'); // 実行される

関数などに想定していない型の引数を渡される可能性があるが、エラーにより後続の処理を止めたくないといった場合に使うような感じでしょうか。

またthrowを使うことにより、意図的に例外を発生させることもできるようです。

function getNumber(x){
  if ( typeof x !== 'number' || isNaN(x) ) {
    throw new Error( 'Parameter is not a number.' ); // 引数が数値ではない場合に例外を発生させる。
  }
  return x;
}

try{
  getNumber( 's' ); // 例外発生により関数の実行が停止し、catchブロックに処理が移る。
} catch(e) {
  console.error(e); // エラー出力 'Error: Parameter is not a number.'
}

本当にざっくりですが、少し理解できてよかった。サイト制作で使う機会は来るのかな…

同一のカスタムフィールド値を持つ投稿の前後記事リンクを出力する

前に一度やったことがあるが忘れていたのでメモ。

ぜろみやさんのブログでやってるの見たな…と思いつつ、まず自力でやってみようと思い実装しました。 以下ソース。

<?php
/**
 * 同一のカスタムフィールドを持つ前後リンクの出力
 * 
 * 取得手順
 * (1) 対象となるカスタムフィールドの投稿をサブループで全件取得する。
 * (2) (1)で取得した投稿内での、現在の記事のインデックスを取得する。
 * (3) (2)で取得したインデックスをもとに前後の記事のパーマリンクを取得する。
 * (4) 取得した前後リンクを出力する。
 */

// (1)
$current = $post;
$currentID = $current->ID;
$postIDs = array();

$args = array(
  'post_type' => $current->post_type, // 任意の投稿タイプ
  'posts_per_page' => -1, // -1で全件取得する
  'post_status' => 'publish',
  'order' => 'DESC',
  'orderby' => 'date',
  'meta_query' => array(
    array(
      'key' => 'hogehoge', // 任意のカスタムフィールド名
      'value' => 1,
      'compare' => '=',
    )
  )
);

$new_query = new WP_Query( $args );
  if( $new_query -> have_posts() ){
    while($new_query -> have_posts()){
      $new_query -> the_post();
      $postIDs[] = get_the_ID();
  }
}
wp_reset_postdata();

// (2)
$currentIndex = array_search( $currentID$postIDs );

// (3)
$prev_link = $currentIndex === count($postIDs) - 1 // 表示している記事がもっとも新しいかどうか判定
          ? ''
          : '<a href="' . get_permalink($postIDs[$currentIndex + 1]) . '">以前の記事へ</a>';

$next_link = $currentIndex === 0 // 表示している記事が最新かどうか判定
          ? ''
          : '<a href="' . get_permalink($postIDs[$currentIndex - 1]) . '">新しい記事へ</a>';
?>

<?php // (4) 
if ( $prev_link || $next_link ) : ?>
<ul class="adjacentPostLinks">
  <?php if ( $prev_link ) : ?>
    <li><?php echo $prev_link?></li>
  <?php endif?>
  <?php if ( $next_link ) : ?>
    <li><?php echo $next_link?></li>
  <?php endif?>
</ul>
<?php endif; ?>

どの記事が前後になるか?は実際に記事を取得してみないとわからないため、サブループで記事を取得してそこから抽出する形になっています。

実装した後にぜろみやさんの記事を見てみたら、同じく全件取得する形で実装されており一安心。変な実装の仕方ではないようなのでよかったです。

参考

Google FontsのNoto Sans JPにfont-feature-settingsが効くようになってる

タイトルの通りなのですが、いつからかはわかりませんがfont-feature-settings: 'palt' 1が有効となり文字詰めを行えるようになってるみたいです。

See the Pen Noto Sans JP font-feature-settings テスト by saiko (@saiko1988) on CodePen.

また文字詰めできなくなるとか起きないかな…信用していいものか…

非同期で取得したデータがIE11で文字化けする場合の対処法

axiosでデータを取得後にDOM操作を行おうとしたところ、IE11のみ文字化けする事例があったのでメモ。

発生状況

以下のようにresponseType: 'document'を指定して取得したところ、IE11のみ文字化けが発生。

axios.get( '取得したいデータのURL', { responseType: 'document' } )
  .then( res => res.data )
  .then( data => {
    console.log( data ); // IEで文字化けする
  } );

取得したいデータの文字コードUTF-8でない可能性もあったのですが、根本の原因はわからず…。

ただresponseType: 'document'を指定しない場合文字化けは発生しないので、いったん無指定で取得した後にDocumentオブジェクトに変換すればよさそう。

何か方法はないかなーと検索したところ、DOMParserというAPIがありました。

DOMParser - Web API | MDN

DOMParser インターフェイスは、 XML や HTML ソースコードを文字列から DOM の Document に解釈する機能を提供します。

上記のコードを以下のように修正。するとIE11でも文字化けなく取得することができました。

axios.get( '取得したいデータのURL' )
  .then( res => res.data )
  .then( data => {
    const domParser = new DOMParser();
    const doc = domParser.parseFromString( data, 'text/html' );
    console.log( doc );
  }

dl要素内のdivの使い方についてメモ

HTML5.2よりdl要素内でdiv要素が使用できるようになったのですが、誤解していた部分があったのでメモ。

単純に「dl要素の子孫要素としてdivが使える」と覚えておりdiv要素をdd要素のラッパーとして使おうとしていたのですが、HTML Living Standardに反する使い方だったようです1

<!-- これはNG -->
<dl>
  <dt></dt>
  <div>
    <dd></dd>
    <dd></dd>
    <dd></dd>
  </div>
</dl>

dd要素の前に配置される兄弟要素はdtまたはdd要素と決まっており、この点が仕様違反となっていました。

つまり、dl要素内でdivを使う際には、dtおよびdd要素をまとめてラップする形で使用するのが仕様に沿った使い方となります。

<!-- これはOK -->
<dl>
  <div>
    <dt></dt>
    <dd></dd>
    <dd></dd>
    <dd></dd>
  </div>
</dl>

ただ上記の形では、dd要素群をひとまとまりに扱いたい場合に少し不都合があります。そのため今回は仕様に合った形で下記のように書き換えました。

<!-- 仕様に合う形に書き換え -->
<dl>
  <dt></dt>
  <dd>
    <ul>
      <li></li>
      <li></li>
      <li></li>
    </ul>
  </dd>
</dl>

ネストが増えているのが少し気持ち悪いですが、そこは仕方ないということで。

参考


  1. 2021.2.10現在

配列に変換し、かつmapで処理する

Array.from()Array.prototype.map()の組み合わせでもできますが、実はArray.from()だけでできます。

Array.from( '12345', i => i * 2 ); // [ 2, 4, 6, 8, 10 ]

Array.from()の第2引数にはmap関数を書くことができるため、わざわざ別に関数を書かなくてもArray.from()のみでmap処理まで完結させることができます。

[参考]