下のロジックは、api層でajax同期コードを使って「this.url」から取得したデータを
view層にreturnする内容になります。
このように同期処理をしておいた場合、send()が呼び出されてからすぐAPIから応答がありません。
データがいるはずが全くないため、このようなやり方では、実際にデータ処理をすることができません。
このような場合に非同期を通じて対応することができます。
同期コード
getRequest<AjaxResponse>(): AjaxResponse {
this.ajax.open('GET', this.url, false);
this.ajax.send();
return JSON.parse(this.ajax.response) as AjaxResponse;
}
非同期処理のためにajaxがaddEventリスナーを提供します。
"load"が呼び出されるとajax.responseに応答値が入っていることがわかります。
ここで問題は!同期コードを見ると、応答値をリターンしますが、
非同期コードではリターンする対象がないことが問題になります。
この場合は、「コールバック」関数を受け取って、
そのコールバック関数を通じて呼び出し元に値を伝えれば良いです。
非同期コード
// コールバック関数を"callback"にて受取って、AjaxResponseタイプのdataを引数にて渡します。
// コールバック関数のtypeはvoid!
// callbackで受け取ったコールバック関数にJSON.parseしたデータを引数にてヨビダシ元に!
// callback: (data: AjaxResponse) == コールバック関数: 引数:引数のタイプ
getRequest<AjaxResponse>(callback: (data: AjaxResponse) => void): void {
this.ajax.addEventListener('load', () => {
callback(JSON.parse(this.ajax.response) as AjaxResponse);
});
this.xhr.send();
}
下のロジックは、api層に存在してて
view層 → getData() → getRequest() です。
api層であるため、実際のデータを受ける側は、viewのため
viewから受取ったコールバック関数をそのままgetRequset渡しています。
getRequest()呼び出し元
// 同期コード
getData(): NewsDetail[] {
return this.request<NewsDetail[]>();
}
// 非同期コード
getData(callback: (data: NewsDetail) => void): void {
return this.getRequest<NewsDetail>(callback);
}
以下はview層の非同期対応コードです。
view層
// 同期コード
render = (id: string): void => {
const api = new NewsDetailApi(CONTENT_URL.replace('@id', id));
const {title, content, comments } = api.getData();
}
// 非同期コード
// 非同期コードに修正したgetData()は、もうreturnをしなくなったので
// getData()にコールバック関数を渡します。
// 結局、getRequestの「JSON.parse(this.ajax.response) as AjaxResponse)」の結果 == data
// になります!
render = (id: string): void => {
const api = new NewsDetailApi(CONTENT_URL.replace('@id', id));
api.gatData((data: NewsDetail) => {
const {title, content, comments } = data;
this.store.makeRead(Number(id));
this.setTemplateData('comments', this.makeComment(comments));
this.setTemplateData('currentPage', this.store.currentPage.toString());
this.updateView();
})