JavaScript request-promise

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が実行される。
書いてみるととても不思議な動きに見える。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です