はじめに
SharePoint Framework にて SharePoint REST API を呼び出す方法について、Promise チェーンを書く際にあまりにも煩雑に感じた部分があったので、その点を解消するための自分なりのやり方をメモしました。
Promise を使った SharePoint REST API 呼び出しのサンプル
GET 処理
概ね以下のようなコードになるかと思います。
ちなみにこの例は、指定のリストの指定のアイテム ID のアイテムについて列を指定してデータを取得するものとなります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const url: string = `${this.context.pageContext.web.absoluteUrl}/_api/web/lists/getbyid('${this.context.pageContext.list.id.toString()}')/items(${itemId})?$select=${selectFields}`; this.context.spHttpClient.get(url, SPHttpClient.configurations.v1) .then((response: SPHttpClientResponse) => { response.json().then((json: any) => { if (response.ok) { // 成功時の処理 } else { // 失敗時の処理 } }).catch((error: any) => { // 失敗時の処理 }); }).catch((error: any) => { // 失敗時の処理 }); |
spHttpClient.get メソッドの戻り値である response は REST の URL が違っている場合や呼び出しが失敗した場合については catch に処理が流れますが、SharePoint 内で問題が起きて REST が正しく動作しないような時は、処理は then に流れて、response.ok プロパティが false になります。
そのため、上記コードでは then の中で response.ok プロパティをチェックし false だった場合の処理(失敗時の処理)を入れています。
こうやって見ると、get をするだけでも、結構煩雑なことが分かります。
POST 処理
GET 処理との違いは、POST するデータを spHttpClient.post メソッドの第 3 引数に渡す必要があるところだけで、他は GET と同じです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | const dataJSON: any = '{"Title":"test","Body":"test"}'; const options: ISPHttpClientOptions= { body: JSON.stringify(dataJSON) }; const url: string = `${this.context.pageContext.web.absoluteUrl}/_api/web/lists/getbyid('${this.context.pageContext.list.id.toString()}')/items`; this.context.spHttpClient.post(url, SPHttpClient.configurations.v1,options) .then((response: SPHttpClientResponse) => { response.json().then((json: any) => { if (response.ok) { // 成功時の処理 } else { // 失敗時の処理 } }).catch((error: any) => { // 失敗時の処理 }); }).catch((error: any) => { // 失敗時の処理 }); |
戻り値及び Promise の処理の共通化
spHttpClient.get メソッドも spHttpClient.post メソッドも、メソッドを呼び出した後の戻り値の処理と Promise の処理が煩雑です。
この煩雑さを低減したいと考え、以下のように callRestApi というファンクションを作って処理を共通化してみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | private callRestApi(restApi: Promise<SPHttpClientResponse>): Promise<any> { return new Promise((resolve: (value: any) => void, reject: (reson?: any) => void) => { restApi.then((response: SPHttpClientResponse) => { response.json().then((json: any) => { if (response.ok) { resolve(json); } else { Log.error(LOG_SOURCE, json.error); reject(json.error); } }).catch((error: any) => { Log.error(LOG_SOURCE, error); reject(error); }); }).catch((error: any) => { Log.error(LOG_SOURCE, error); reject(error); }); }); } |
callRestApi ファンクションを利用した GET 処理
callRestApi ファンクションを使うと GET 処理のコードが 9 行削減できます。
1 2 3 4 5 6 | const url: string = `${this.context.pageContext.web.absoluteUrl}/_api/web/lists/getbyid('${this.context.pageContext.list.id.toString()}')/items(${itemId})?$select=${selectFields}`; this.callRestApi(this.context.spHttpClient.get(url, SPHttpClient.configurations.v1)).then((json: any) => { // 正常時の処理 }).catch((error: any) => { // 異常時の処理 }); |
callRestApi ファンクションを利用した POST 処理
POST 処理も GET 処理と同様に 9 行コードを削減できます。
1 2 3 4 5 6 7 8 9 10 | const dataJSON: any = '{"Title":"test","Body":"test"}'; const options: ISPHttpClientOptions= { body: JSON.stringify(dataJSON) }; const url: string = `${this.context.pageContext.web.absoluteUrl}/_api/web/lists/getbyid('${this.context.pageContext.list.id.toString()}')/items`; this.callRestApi(this.context.spHttpClient.post(url, SPHttpClient.configurations.v1, options)).then((json: any) => { // 正常時の処理 }).catch((error: any) => { // 異常時の処理 }); |
まとめ
煩雑な処理を共通化することで、9 行のコードを削減することができました。
1 回の REST API コールであれば大差ありませんが、Promise チェーンを組んで複数の REST API コールをする際にはこの削減効果は大きくなります。
もっと短縮する方法もありそうですが、現在私が書いている書き方を紹介させていただきました。