ionic, angular(RxJS), JSONP 別ドメインサーバにファイルを置いただけの取得サンプル
この例はゲームブックのシナリオデータをどこかに置いて、そのアドレスをゲームブックアプリで指定すれば他の人の作ったシナリオデータを使えるのではないかと言う目的のサンプルです。(サーバでの処理はない)
モバイルアプリを初めて作る開発日記的な文章なので、必ずしも正しい方法とは限りませんのでご注意を!
(一応、Android実機では動作を試しましたが、Angular以外じゃダメだと思います。)
見に来た方が多くなっていますので、一応ご注意を!
前回、ドメインをまたいで(CORSの制限に引っかからないで)データの取得が成功しました。
以下は、ionic(type:angular)での最小セッティングのサンプルです。
外部データ例(サーバ側にプログラム等は無いので直接リンクからアクセス)
---------------------------------------------------------------
ng_jsonp_callback_0({"singleParameters":[{"name":"Status","type":"STRING","value":"OK"},{"name":"Description","type":"STRING","value":""}]})
---------------------------------------------------------------
src\app\app.module.ts
//HttpClientModule, HttpClientJsonpModule,を追加
---------------------------------------------------------------
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
//HttpClientModule, HttpClientJsonpModule,を追加
import { HttpClientModule, HttpClientJsonpModule } from '@angular/common/http';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
@NgModule({
declarations: [AppComponent],
//HttpClientModule, HttpClientJsonpModule,を追加
imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, HttpClientModule, HttpClientJsonpModule,],
providers: [{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy }],
bootstrap: [AppComponent],
})
export class AppModule {}
---------------------------------------------------------------
src\app\home\home.page.ts
---------------------------------------------------------------
import { Component } from '@angular/core';
//追加
import {Subscription} from 'rxjs';
//追加
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-home',
templateUrl: 'home.page.html',
styleUrls: ['home.page.scss'],
})
export class HomePage {
private subscription: Subscription;
//取得したデータの受け入れ用
fromJSONP={};
constructor(private http: HttpClient) {
let urlhoge = '(別ドメインの)外部データアドレス';
//Observe
let ObsebTest = this.http.jsonp(urlhoge, '');
ObsebTest.subscribe(this.observer_1);
}
//Subscribe内で動かす関数(と書きましたがよく考えるとJSONなので動作定義と言うべきもの?)
observer_1 = {
next: x => this.testJSON(x), //読み込み成功時
error: error => console.log('Observer1 got an error: ' + JSON.stringify(error)),//エラー時
complete: () => console.log('Observer1 got Complete'), //終了時
}; // データを受け取った時に何をするのかが書かれている
//読み込んだデータを内部変数にコピー
testJSON(x:JSON){
this.fromJSONP=JSON.parse(JSON.stringify(x));
alert(this.fromJSONP["singleParameters"][1]["name"])
}
}
---------------------------------------------------------------
ObsebTest.subscribe(this.observer_1);の部分ですが、別な使い方(定期的に読み込みを行うなど)ならば以下のようにSubscription オブジェクトにセットしてunsubscribe()メソッドで停止させることもあるようです。
---------------------------------------------------------------
import { interval } from 'rxjs';
const observable = interval(1000);
const subscription = observable.subscribe(console.log);
setTimeout(()=>{
subscription.unsubscribe();
},5000)
---------------------------------------------------------------
参照:RxJSの基礎理解|基本的な Subscribe の仕組み
https://zenn.dev/mikakane/articles/rxjs_2_tutorial#%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA-subscribe-%E3%81%AE%E4%BB%95%E7%B5%84%E3%81%BF
外部データについてですが、
ng_jsonp_callback_0(JSONデータ)
と言う形で書かないと、読み込み前に以下のようなエラーで ObsebTest.subscribe(this.observer_1);で落ちます。
(error: error => console.log('Observer1 got an error: ' + JSON.stringify(error)),//エラー時)
エラー内容
---------------------------------------------------------------
Observer1 got an error: {"headers":{"normalizedNames":{},"lazyUpdate":null,"headers":{}},"status":0,"statusText":"JSONP Error","url":"テストファイル名?hogex=ng_jsonp_callback_0","ok":false,"name":"HttpErrorResponse","message":"Http failure response for テストファイル名?hogex=ng_jsonp_callback_0: 0 JSONP Error","error":{}}
---------------------------------------------------------------
hogexは”let ObsebTest = this.http.jsonp(urlhoge, 'hogex');”にした場合。
どこで"ng_jsonp_callback_0"と言う名前を定義しているかは判らなかったですが、使う分には問題ないと割り切りました。
追記:
以下のサイトを見て、少し判った気がします。
なるほどサーバ側で処理しない場合のやり方(ng_jsonp_callback_0(JSONデータ))という訳ですね。
JSONPをごりごり実装するときのポイント|サーバ側の実装
https://qiita.com/stkdev/items/f3e6cae58ab73faee502#%E3%82%B5%E3%83%BC%E3%83%90%E5%81%B4%E3%81%AE%E5%AE%9F%E8%A3%85
Ionic:
Ionic CLI : 6.19.0 (C:\Users\ユーザー名\AppData\Roaming\npm\node_modules\@ionic\cli)
Ionic Framework : @ionic/angular 6.1.7
@angular-devkit/build-angular : 13.2.6
@angular-devkit/schematics : 13.2.6
@angular/cli : 13.2.6
@ionic/angular-toolkit : 6.1.0
Capacitor:
Capacitor CLI : 3.5.1
@capacitor/android : 3.5.1
@capacitor/core : 3.5.1
@capacitor/ios : not installed
Utility:
cordova-res : 0.15.4
native-run : 1.6.0
System:
NodeJS : v16.14.0 (C:\Program Files\nodejs\node.exe)
npm : 8.3.1
OS : Windows 10