この記事の目次
JavaScript の「Promise」とは?

PromiseをSalesforceの開発で利用する利点

Apexクラスを実行するソースコードの可読性が向上する
PromiseとES7以降に利用可能なasync/awaitを利用することで、Apexクラスを実行するJavaScriptのソースコードの可読性が向上できます。 JavaScriptでApexクラスの処理を実行した場合、非同期処理として処理されます。従来の方法では非同期処理を順番に実行する場合、コールバック関数に後続の処理を実装していました。 この方法だと、後続の処理が増えると、コールバック関数のネストが深くなり、可読性が低下するという問題がありました。 そこで、Promiseとasync/awaitを利用すると、非同期処理のコールバック関数を利用せずに、非同期処理が順番に実行できるようになります。非同期処理でコールバック関数を利用せずに済むため、ネストが深くならず、ソースコードが見やすくなるのです。従来の方法でApexクラスを実行した場合
従来の方法では、TestMethod1()実行後にTestMethod2()を実行した場合、以下のようにコールバック関数内のネストが深くなり、ソースコードが見づらくなります。import ApexMethod1 from '@salesforce/apex/ApexTest.TestMethod1';
import ApexMethod2 from '@salesforce/apex/ApexTest.TestMethod2';
handleOKClick(event) {
// ApexTestクラスのTestMethod1()を実行
TestMethod1({param1: 1})
.then((result1) => {
// ApexMethod1()の実行結果が正常な場合の処理
// TestMethod2()の実行
TestMethod2({param2: 2})
.then((result2) => {
// TestMethod2()の実行結果が正常な場合の処理
})
.catch((error2) => {
// TestMethod2()の実行中のエラー処理
});
})
.catch((error1) => {
// TestMethod1()の実行中のエラー処理
});
}
Promiseとasync/awaitを利用して、Apexクラスを実行した場合
Apexクラスを実行した場合、非同期処理として扱われるため、実行結果はPromiseに格納されます。そのため、async/awaitを利用することで、コールバック関数を利用しなくても非同期処理を順番に実行することが可能です。import ApexMethod1 from '@salesforce/apex/ApexTest.TestMethod1';
import ApexMethod2 from '@salesforce/apex/ApexTest.TestMethod2';
async handleOKClick(event) {
// TestMethod1()を実行
var result1 = await TestMethod1({param1: 1});
// TestMethod1()の実行完了後、TestMethod2()を実行
var result2 = await TestMethod2({param2: 2});
}
非同期処理で順番に実行する関数間の独立性が向上する
Promiseとasync/awaitを利用することで、非同期処理のソースコードの可読性を向上するだけではなく、関数間の独立性も向上します。 従来の方法では、非同期処理のコールバック関数に後続の処理を実装するため、処理ごとにテストができず、コールバック関数全体でテストしていました。 しかし、JavaScriptの処理ごとにPromiseのインスタンスを生成し、非同期処理とすることで、Apexクラスのようにasync/awaitで処理の順番が制御可能です。また、JavaScriptの各処理で独立しているため、処理ごとにテストも実施できるようになります。従来の方法で非同期処理を実装した場合
従来の方法で非同期処理を実装した場合、以下のように住所検索のコールバック関数内に市外局番検索が実装されているため、市外局番検索単体ではテストができません。handledChange(event) {
var zipcode = event.target.value;
// 郵便番号から住所を検索
$.ajax({
url: 'https://XXX/zipcode/search'
data: { zipcode: zipcode }
})
.done(function (res1) {
// 市外局番検索結果が正常な場合の処理
// 住所を画面項目に設定
setAddress(res1);
// 住所の県名から市外局番を検索
$.ajax({
url: 'https://XXX/areacode/search'
data: { prefecture: res1.result.address1}
})
.done(function (res2) {
// 市外局番検索結果が正常な場合の処理
})
.fail(function (err2) {
// 市外局番検索時のエラー処理
});
})
.fail(function (err1) {
// 住所検索時のエラー処理
});
}
PromiseのコンストラクタにJavaScriptの処理を実装した場合
住所検索と市外局番検索でそれぞれPromiseのインスタンスを生成し、async/awaitで処理の順番を制御します。このように実装することで、ソースコードのステップ数は増えますが、住所検索と市外局番検索を別々にテストできるようになります。// 郵便番号から住所を検索
function getAddress(zipcode) {
return new Promise(function (resolve, reject) {
$.ajax({
url: 'https://XXX/zipcode/search'
data: { zipcode: zipcode }
})
.done(function (ret) {
resove(ret);
})
.fail(function (err) {
reject(err);
});
});
}
// 住所の県名から市外局番を検索
function getAreacode(prefecture) {
return new Promise(function (resolve, reject) {
$.ajax({
url: 'https://XXX/areacode/search'
data: { prefecture: prefecture }
})
.done(function (ret) {
resove(ret);
})
.fail(function (err) {
reject(err);
});
});
}
async handledChange(event) {
try{
var zipcode = event.target.value;
// 郵便番号から住所を検索
var addressData = await getAreacode(zipcode);
// 住所の県名から市外局番を検索
var areacodeData = await getAreacode(addressData.result.address1);
} catch(err){
// error処理
// 各関数のreject()が実行されるとその引数がerrに格納される
}
}
Promiseを使って実装してみよう

この記事の監修者・著者

-
未経験からITエンジニアへのキャリアチェンジを支援するサイト「キャリアチェンジアカデミー」を運営。これまで4500人以上のITエンジニアを未経験から育成・排出してきました。
・AWS、salesforce、LPICの合計認定資格取得件数:2100以上(2023年6月時点)
・AWS Japan Certification Award 2020 ライジングスター of the Year 受賞