request-promiseを入れ子にしたときどうなるか検証する。
phpでslimフレームワークで以下のようなレスポンスになるようにする。
http://localhost:8080/getJson
["1","2","3"]
http://localhost:8080/check/{count}
2は["OK"]、1、3は["NG"]を返すようにする。
# 2
["OK"]
# 1 or 3
["NG"]
slimで書くと以下のようになります。
※routes.phpのみ記載します。
<?php
use Slim\Http\Request;
use Slim\Http\Response;
// Routes
$app->get('/getJson', function (Request $request, Response $response, array $args) {
$json = ['1', '2', '3'];
return $response->withJson($json);
});
$app->get('/check/{count}', function (Request $request, Response $response, array $args) {
if( $args['count'] === "2" ) {
$json = ['OK'];
return $response->withJson($json);
} else {
$json = ['NG'];
return $response->withStatus(404)->withJson($json);
}
});
phpのビルドインサーバの起動方法
$ php -S localhost:8000 -t public public/index.php
このときに、node.jsでgetJsonを叩く。
その結果を使って、ループを回してcheckを叩く。
1はNG。2はOK。3は叩かれないことを検証する。
この仕様を満たすように以下のコードを作成した。
※以下のコードは仕様を満たせていません。。
$ cat a.js
var rp = require('request-promise');
rp('http://[::1]:8080/getJson')
.then(function (json) {
const parse = JSON.parse(json);
parse.some(function(value) {
console.log(value);
rp('http://[::1]:8080/check/'+value)
.then(function(json) {
console.log('success='+value);
return true;
})
.catch(function (err) {
console.log('error='+value);
return false;
})
});
})
.catch(function (err) {
console.log(err);
});
※ 持ってたPCだと、localhost、127.0.0.1でも叩くことができなかった。なのでIPv6の指定方法で叩いています。
実行してみると
$ node a.js
1
2
3
error=1
success=2
error=3
error=3まで実行されてしまった。
原因としては、promiseで処理しているため。
5行目が処理される。つまり1が処理されていく。
7行目が処理されていくが、request-promiseの処理でブロックされないため、リクエスト処理より前に5行目に戻る。つまり2が処理されていく。同様に処理はブロックされず、3が処理されていく。
リクエスト処理が戻ってきたタイミングで9行目、13行目にあるconsole.logが実行される。
書いてみるととても不思議な動きに見える。