2

私はこのコードでテストします:

get_fee(Transaction,SourceNumber,Amount, Currency) ->
Url = lists:concat(["http://localhost/test.php","?transaction=", Transaction, "&saccount=", SourceNumber,Amount,"&currency=",Currency]),
        inets:start(),
        {Flag, Response} = http:request(get, {Url, []}, [], []),
        case Flag of
            ok ->
                { { _, ReturnCode, _ }, _, Body } = Response,

                if ReturnCode =:= 200 ->
                        {ok,{_,[{_,Code},{_,Permission},{_,Payer},{_,Payee}]}} = json:decode_string(Body),
                            case Permission of true ->
                                if Code =:= 200 ->
                                    {ok,{Code, Payer, Payee}};
                                Code =:= 204 ->
                                    {nok,{Code, not_found}};
                                true ->
                                    {nok,{Code, parameter_error}}
                                end;
                            false ->
                                {nok,{Code, parameter_error}}
                            end;
                    true->
                        {error, http_error}
                end;
            error ->
                case Response of
                    nxdomain -> {error, dns_error};
                    _ -> {error, network_error}

                end
        end.

httpからの応答は次のとおりです。 {"code":200,"permission":true,"fee_payer":0,"fee_payee":19}

しかし今、私は同じ考えをするのが好きですが、この場合のhttpの戻り値は次のとおりです:

{"CIN":"08321224","Name":21}

この場合、CINと名前だけがあります

以前を変更しようとしています

get_fee(Num) ->
    Url = lists:concat(["http://localhost/GTW/Operation.php","?ACCOUNT_NUM=", Num]),




            inets:start(),
             {Flag, Response} = http:request(get, {Url, []}, [], []),
            case Flag of
                ok ->
                    { { _, ReturnCode, _ }, _, Body } = Response,
                    %% for debug
                   io:format("~p~n",[ReturnCode]),
                    if ReturnCode =:= "08321224" ->
                            {ok,{_,[{_,CIN},{_,Name}]}} = json:decode_string(Body),
                                case Name of 21 ->
                                                 io:format(CIN),
                                                 io:format(Name),
                                    if CIN =:= "08321224"->
                                        {ok,{CIN, Name}};
                                    CIN =:= 204 ->
                                        {nok,{CIN, not_found}};
                                    true ->
                                        {nok,{CIN, parameter_error}}
                                    end;
                                false ->
                                    {nok,{CIN, parameter_error}}
                                end;
                        true->
                            {error, http_error}
                    end;
                error ->
                    case Response of
                        nxdomain -> {error, dns_error};
                        _ -> {error, network_error}
                    %% for debug
                    %%io:format("pass2~n ~p~n",[Response]),
                    end
  end.

しかし、それは表示されます:

test:get_fee("0001").
200
{error,http_error}
4

2 に答える 2

7

Erlang のセマンティックな考え方に従えば、はるかにうまくいくので、ここではスタイルを細かく取り上げます。

get_fee(Num) ->
    Url = lists:concat(["http://localhost/GTW/Operation.php","?ACCOUNT_NUM=", Num]),
    inets:start(),

ここから始めるのは間違っていinetsます。これを行うだけでよいため、この関数の外で開始する必要があります。

{Flag, Response} = http:request(get, {Url, []}, [], []),

この部分は、パターン マッチでより適切にコーディングされます。との識別はFlagResponse単純な一致で直接デコードできます。書く、

case http:request(get, {Url, []}, [], []) of
  {ok, {{_, 200, _}, _, Body}} ->
      {ok, R} = json:decode_string(Body),
      get_fee_decode_(get_cin(R), get_name(R));
  {error, Reason} -> {error, Reason}
end.

いずれにせよ、このケースを完全にコード化するため、に変更{error, nxdomain}しないことをお勧めします。エラータプルを呼び出し元に渡して、呼び出し元に処理させるだけです。{error, dns_error}nxdomain

get_fee_decode_("08321224" = CIN, 21 = Name) -> {ok, {CIN, Name}};
get_fee_decode_("204" = CIN, 21) -> {nok, {CIN, not_found}};
get_fee_decode_(CIN, _Name) -> {nok, {CIN, parameter_error}};

このような新しい関数を導入して、コード ベースの内部部分を処理します。そして、マッチングをトップレベルに上げます。これは、コードを関数に分離することにより、長期的に役立ちます。

JSON 構造では、「オブジェクト」に順序がないため、構造が

{"code":200,"permission":true,"fee_payer":0,"fee_payee":19}

しかし、JSON によれば、デコードはこの構造を保持する必要はありません。したがって、有効なデコードは次のようになります。

[{"fee_payee", 19}, {"fee_payer", 0}, {"permission", true}, {"code", 200}]

これはコード内で一致しないため、後で厄介なエラーが発生する可能性があります。

次のようなものが必要です。

get_fee_payer(PL) -> proplists:get_value("fee_payer", PL).

プログラミング スタイルで問題になるもう 1 つのことは、エラー情報のケースを隠していることです。Erlang では、多くの場合、コードの「ハッピー パス」のみを処理するだけで済み、コード ベースにどのような種類のエラーがあるかがわかるまで、すべてのエラー処理を省略できます。その後、ゆっくりとエラー処理を追加し始めることができます。防御的プログラミングは、回避できるのであれば行うべきことではありません。

于 2012-12-20T10:50:04.840 に答える
2

あなた、変ったね:

if ReturnCode =:= 200 ->

に:

if ReturnCode =:= "08321224" ->

ただし、それはあなたのバージョンで同じままである必要があります。200 は「OK」の HTTP ステータス コードです。ここでの最初のステップは、サーバーが実際にリクエストを処理し、肯定的な応答を返したことを確認することです。その番号は でのみ見つかりますBody- それがこのif CIN =:= "08321224"->部品の目的です。

于 2012-12-20T10:19:43.720 に答える