-
Promise は、JavaScript において、非同期処理のコールバック関数をより分かりやすく記述するための仕組みです。
非同期処理のコールバック関数の説明のため以下の様な関数があるとします。■コールバック関数の説明のための例
function test_callback(timeoutval, callback_func) { setTimeout(() => { callback_func(); }, timeoutval); }
この関数は時間を待った後で指定コールバック関数の実行するものです。
これを実際に使う場合は以下の様になります。// 非同期関数を用いて test_callback(1000, function() { console.log('callback...1000'); });
1000msec待って、「callback...1000」をデベロッパーツールのコンソールに出力されます。
■Promiseを使って上記の例を書き変えてみる
先ずはPromiseの説明ですが、Promiseオブジェクトの生成には2個関数の引数を持った関数を渡します。
以下の説明では2個の関数の引数名として「resolve」「reject」としていますが、 それぞれがPromise渡される関数内で処理成功時と失敗時の処理を行う関数を指定します。
引数関数の名前が「resolve」「reject」ですが、別にこの名前ではなくても他のものでも問題ありません。
また、「resolve」のみでもOKです。// Promiseの生成 const Promise = new Promise((resolve, reject) => { // ここで何かの処理 // … if ( [成功]/[失敗]の判定 ) { resolve("OK"); // [成功] } else { reject("NG"); // [失敗] } }); // Promiseの実行 Promise.then((result) => { // 成功時は「resolve」から渡されるものが「result」に返される console.log(result); // "OK"が表示される }) .catch((error) => { // 失敗時は「reject」から渡されるものが「error」に返される console.log(error); // "NG"が表示される });
上記のことを踏まえて、最初のコールバック関数の例を以下の様にします。
function test_callback2(timeoutval) { return new Promise((resolve) { setTimeout(function() { resolve(timeoutval); // 成功時の関数をコール }, timeoutval); }); }
これを実行するために以下の様にします。
test_callback2(1000).then((result) => { console.log('callback...' + result); });
結果コンソールには、1000msec待ってから「callback...1000」が出力されます。
結果的には Promise を使ってもさほど違いはありませんが、 最初の例の関数を、コールバック後の処理を繰り返したい場合に以下の様な記述になります。// コールバック関数のネストが深い!! test_callback(1000, function() { console.log('callback...1000'); test_callback(2000, function() { console.log('callback...2000'); test_callback(3000, function() { console.log('callback...3000'); }); }); });
1000msec待って「callback...1000」がコンソールに出力され、 その後、2000msec待って「callback...2000」が、さらに3000msec待って「callback...3000」が出力されます。
この感じではネストが深くなり、ソースが見にくいと思います。 これを解消する為に上記の Promise を使った関数を使用します。
■Promiseを使った処理の連結の例
// コールバック用の関数を再掲 function test_callback2(timeoutval) { return new Promise((resolve) { setTimeout(function() { resolve(timeoutval); // 成功時の関数をコール }, timeoutval); }); } // then で連結する test_callback2(1000).then((result) => { console.log('callback...' + result); return test_callback2(2000); }).then((result) => { console.log('callback...' + result); return test_callback2(3000); }).then((result) => { console.log('callback...' + result); });
最初の test_callback2 の then では成功時の処理を書きますが、コンソール出力後 再度、 test_callback2 を実行し、結果を return しています。 よって、この then の結果では return で Promise オブジェクトが返されてくるので さらに then で成功時の処理を書きます。
こうやって順次 then で結合することで、ネストが深くなることを防ぐことができます。
また、順次処理を行うことができます。
関連する記事
⇒JavaScript 何に使う
⇒JavaScript jQueryの使い方(セレクタ)
⇒JavaScript jQueryの使い方(セレクタ)その2
⇒JavaScript 関数の宣言について(function)
⇒JavaScript jQueryでJavascriptファイルの動的に変更する方法
⇒JavaScript jQueryを使った checkbox の操作方法
PR -
表示される行番号にはエラーが無く、他の部分にエラーが在る場合が多いです。
例えば、if文などの{(中括弧)の閉じ忘れなどがあります。
また、今回くだらないミスを起こしたのですが、変数名の先頭の【$】ドルマークを忘れたことです。
長い変数名を使用していて、他の所からのコピペでささっとソースを直したら 【$】ドルマークをつけるのを忘れていて、解決するまで30分も掛かってしまいました。
{(中括弧)の閉じ忘れを中心に見直していたのですが、人間正しいと思いこむと 簡単な変数の【$】ドルマークを忘れるものです。笑ってやってください。
皆さんもくれぐれも変数の先頭の【$】ドルマークを忘れませんように。
尚、エラーの部分を特定する方法としては、 エラーが起きている部分を含む大まかなところで、 【/**/】コメントにしてエラーが出ない様にしてから、 順次内側にコメント部分を狭めていき見つける様にしています。
-
今日は、またまた簡単なエラーの件で恐縮ですが、 以下のソースで、「L_test()」の宣言でタイトルのエラーが発生しました。
「処理A」「処理B」共に長い処理だったので、なかなか見つからなかったのですが、 よくよく見ると、「switch」文の閉じる括弧「}」がありません。
こんな簡単なところにバグが潜んでいました。
論理的には問題無い様な感じだったので、括弧「{}」の対応をチェックするのを怠っていました。 完全にケアレスミスでした。
「unexpected 'private'」などと表示されたので、てっきり他の部分を疑っていましたが、 もっとソースをよく見るべきでした。
タイトルの様なエラーが出たら、一度処理の括りの括弧「{}」の対応を確認してみては 如何でしょうか。public function P_test($intMode){ $blnRet = true; // ----- // 処理A // ----- if($blnRet == true){ switch($intMode){ case 1: // 新規 case 2: // 修正 // ----- // 処理1 // ----- break; case 3: // 削除 // ----- // 処理2 // ----- break; default: } // ----- // 処理B // ----- } private function L_test(){ $blnRet = false; // 何か処理する }
-
POSTやGETなどのスーパーグローバル変数へのアクセスは直接以下の様にすることで行えます。
この例では、$_GET変数から id という引数を取得します。<?php if((isset($_GET["id"]) == false) || ($_GET["id"] == "")) { $id = ''; }else{ $id = $_GET["id"]; } ?>
これを filter_input 関数を使うと1行ですっきりします。<?php $id = filter_input(INPUT_GET, 'id'); ?>
但し、これだと引数 id が全く指定されない場合は、変数 $id の中身がNULLになってしまいます。 そこで filter_input 関数の第3引数に FILTER_SANITIZE_STRING を指定すれば id を文字列として 取得できます。<?php $id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_STRING); ?>
引数 id を整数値として扱いたい場合は、第3引数に FILTER_VALIDATE_INT を指定します。<?php $id = filter_input(INPUT_GET, 'id', FILTER_SANITIZE_STRING); ?>
この場合でも、id=aaa の文字列指定であったり、id= の様に未指定であったりすると 変数 $id が false で返されます。
これでは不都合があったりしますので、値の規定値、最小値、最大値の指定を filter_input 関数の第4引数に配列で指定します。<?php $id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT, array('options' => array('default' => 0, 'min_range' => 0, 'max_range' => 999) ) ); ?>
指定された min_range指定値と max_range指定値の範囲外の場合は default指定値が返されます。
-
画像ファイルのアップロードでBMPファイルをJPGに変換する時に imagecreatefromwbmpを使ったがうまくいかない現象が発生しました。 以下の様なソースで、画像ファイルの種類としては「jpeg」「bmp」「png」「gif」を 対象としていたのですが、「bmp」用の関数「imagecreatefromwbmp」がうまく動作しませんでした。
// 画像ファイル名のチェック if (!empty($_FILES['fileImage']['name'])) { $strExt = strtolower(pathinfo($_FILES['fileImage']['name'], PATHINFO_EXTENSION)); // ファイル拡張子が正常の場合 switch ($strExt) { case "jpg": case "jpeg": $im = @imagecreatefromjpeg($_FILES['fileImage']['tmp_name']); break; case "bmp": $im = @imagecreatefromwbmp($_FILES['fileImage']['tmp_name']); break; case "png": $im = @imagecreatefrompng ($_FILES['fileImage']['tmp_name']); break; case "gif": $im = @imagecreatefromgif ($_FILES['fileImage']['tmp_name']); break; default: $im = FALSE; break; } //JPEGファイルへの変換 if (!$im) { imagejpeg($im, 'test.jpg'); } }
何度やってもうまくいかないので、PHPの正式な関数の説明書を見ると 以下の関数の投稿が載っていました。
ダメもとで一度この関数で行うと取り敢えず処理がうまくいったのでこれでOKとしました。/*********************************************/ /* Fonction: ImageCreateFromBMP */ /* Author: DHKold */ /* Contact: admin@dhkold.com */ /* Date: The 15th of June 2005 */ /* Version: 2.0B */ /*********************************************/ function ImageCreateFromBMP($filename) { //Ouverture du fichier en mode binaire if (! $f1 = fopen($filename,"rb")) return FALSE; //1 : Chargement des ent?tes FICHIER $FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14)); if ($FILE['file_type'] != 19778) return FALSE; //2 : Chargement des ent?tes BMP $BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'. '/Vcompression/Vsize_bitmap/Vhoriz_resolution'. '/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40)); $BMP['colors'] = pow(2,$BMP['bits_per_pixel']); if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset']; $BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8; $BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']); $BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4); $BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4); $BMP['decal'] = 4-(4*$BMP['decal']); if ($BMP['decal'] == 4) $BMP['decal'] = 0; //3 : Chargement des couleurs de la palette $PALETTE = array(); if ($BMP['colors'] < 16777216) { $PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4)); } //4 : Cr?ation de l'image $IMG = fread($f1,$BMP['size_bitmap']); $VIDE = chr(0); $res = imagecreatetruecolor($BMP['width'],$BMP['height']); $P = 0; $Y = $BMP['height']-1; while ($Y >= 0) { $X=0; while ($X < $BMP['width']) { if ($BMP['bits_per_pixel'] == 24) $COLOR = unpack("V",substr($IMG,$P,3).$VIDE); elseif ($BMP['bits_per_pixel'] == 16) { $COLOR = unpack("n",substr($IMG,$P,2)); $COLOR[1] = $PALETTE[$COLOR[1]+1]; } elseif ($BMP['bits_per_pixel'] == 8) { $COLOR = unpack("n",$VIDE.substr($IMG,$P,1)); $COLOR[1] = $PALETTE[$COLOR[1]+1]; } elseif ($BMP['bits_per_pixel'] == 4) { $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1)); if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F); $COLOR[1] = $PALETTE[$COLOR[1]+1]; } elseif ($BMP['bits_per_pixel'] == 1) { $COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1)); if (($P*8)%8 == 0) $COLOR[1] = $COLOR[1] >>7; elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6; elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5; elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4; elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3; elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2; elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1; elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1); $COLOR[1] = $PALETTE[$COLOR[1]+1]; } else return FALSE; imagesetpixel($res,$X,$Y,$COLOR[1]); $X++; $P += $BMP['bytes_per_pixel']; } $Y--; $P+=$BMP['decal']; } //Fermeture du fichier fclose($f1); return $res; }