[{"data":1,"prerenderedAt":795},["ShallowReactive",2],{"h2988808419":3,"h3339837976":487,"h2834694947":785},{"id":4,"title":5,"body":6,"description":476,"extension":477,"meta":478,"navigation":482,"path":483,"seo":484,"stem":485,"__hash__":486},"docs\u002Fja\u002Ftips\u002F2026\u002F07\u002F30\u002Fliff-ready.md","どこからでもliff.init()の完了を待てるliff.readyと、その注意点",{"type":7,"value":8,"toc":459},"minimark",[9],[10,11,12,20,25,38,46,69,80,89,106,150,224,243,249,255,270,297,325,328,373,391,395,411,415,444,450,454],"Tips",{},[13,14,17],"h1",{"id":15,"class":16},"","!mb-4",[18,19],"page-title",{},[21,22],"display-date",{"date":23,"class":24},"2026\u002F07\u002F30","!mb-20",[26,27,28,29,37],"p",{},"今回のTipsでは、地味ながら便利なプロパティ",[30,31,33],"a",{"href":32},"\u002Freference\u002Fliff\u002F#ready",[34,35,36],"code",{},"liff.ready","と、その使い方の注意点を紹介します。",[39,40,42,45],"h2",{"id":41},"where-to-await-init",[34,43,44],{},"liff.init()","の完了をどこで待つか",[26,47,48,49,55,56,61,62,65,66,68],{},"LIFFアプリでは、",[30,50,52],{"href":51},"\u002Freference\u002Fliff\u002F#get-profile",[34,53,54],{},"liff.getProfile()","メソッドをはじめ多くのメソッドが、",[30,57,59],{"href":58},"\u002Freference\u002Fliff\u002F#initialize-liff-app",[34,60,44],{},"メソッドの完了後にしか呼べません。アプリの規模が小さいうちは",[34,63,64],{},"liff.init().then(...)","の中にすべての処理を書けば済みますが、処理がモジュールやファイルに分かれてくると、イベントハンドラやユーティリティ関数の側でも「",[34,67,44],{},"の完了後であること」を保証したくなります。",[26,70,71,72,74,75,79],{},"そのための仕組みは自分で用意することもできます。たとえば、",[34,73,44],{},"が返すPromiseをexportして共有したり、初期化が完了したかどうかのフラグを自前で管理したりする方法です。一方で、LIFF SDKにも組み込みのプロパティが用意されています。それが",[30,76,77],{"href":32},[34,78,36],{},"です。",[39,81,83,85,86,88],{"id":82},"decouple-with-liff-ready",[34,84,36],{},"で",[34,87,44],{},"の「呼ぶ場所」と「待つ場所」を分離する",[26,90,91,93,94,96,97,99,100,102,103,105],{},[34,92,36],{},"は、",[34,95,44],{},"の実行が成功したときにresolveされるPromiseを保持するプロパティです。",[34,98,44],{},"を呼ぶ前から参照できるため、「",[34,101,44],{},"はアプリのエントリポイントで1回だけ呼ぶ。その完了を待ちたい場所では",[34,104,36],{},"をawaitする」という分離ができます。",[107,108,112],"pre",{"className":109,"code":110,"language":111,"meta":15,"style":15},"language-javascript shiki shiki-themes github-dark-default","\u002F\u002F エントリポイント: liff.init()はここで1回だけ呼ぶ。エラー処理もここで行う\nliff.init({ liffId: 'YOUR-LIFF-ID' }).catch(handleInitError);\n","javascript",[34,113,114,123],{"__ignoreMap":15},[115,116,119],"span",{"class":117,"line":118},"line",1,[115,120,122],{"class":121},"sH3jZ","\u002F\u002F エントリポイント: liff.init()はここで1回だけ呼ぶ。エラー処理もここで行う\n",[115,124,126,130,134,137,141,144,147],{"class":117,"line":125},2,[115,127,129],{"class":128},"sZEs4","liff.",[115,131,133],{"class":132},"sc3cj","init",[115,135,136],{"class":128},"({ liffId: ",[115,138,140],{"class":139},"s9uIt","'YOUR-LIFF-ID'",[115,142,143],{"class":128}," }).",[115,145,146],{"class":132},"catch",[115,148,149],{"class":128},"(handleInitError);\n",[107,151,153],{"className":109,"code":152,"language":111,"meta":15,"style":15},"\u002F\u002F クリックハンドラやユーティリティ関数: liff.init()の完了だけ待つ\nasync function loadProfile() {\n  await liff.ready;\n  const profile = await liff.getProfile();\n  showDisplayName(profile.displayName);\n}\n",[34,154,155,160,175,184,209,218],{"__ignoreMap":15},[115,156,157],{"class":117,"line":118},[115,158,159],{"class":121},"\u002F\u002F クリックハンドラやユーティリティ関数: liff.init()の完了だけ待つ\n",[115,161,162,166,169,172],{"class":117,"line":125},[115,163,165],{"class":164},"suJrU","async",[115,167,168],{"class":164}," function",[115,170,171],{"class":132}," loadProfile",[115,173,174],{"class":128},"() {\n",[115,176,178,181],{"class":117,"line":177},3,[115,179,180],{"class":164},"  await",[115,182,183],{"class":128}," liff.ready;\n",[115,185,187,190,194,197,200,203,206],{"class":117,"line":186},4,[115,188,189],{"class":164},"  const",[115,191,193],{"class":192},"sFSAA"," profile",[115,195,196],{"class":164}," =",[115,198,199],{"class":164}," await",[115,201,202],{"class":128}," liff.",[115,204,205],{"class":132},"getProfile",[115,207,208],{"class":128},"();\n",[115,210,212,215],{"class":117,"line":211},5,[115,213,214],{"class":132},"  showDisplayName",[115,216,217],{"class":128},"(profile.displayName);\n",[115,219,221],{"class":117,"line":220},6,[115,222,223],{"class":128},"}\n",[26,225,226,228,229,232,233,235,236,239,240,242],{},[34,227,36],{},"の利点は手軽さです。Promiseやフラグを自前で配線しなくても、import済みの",[34,230,231],{},"liff","オブジェクトからそのまま完了を待つことができます。",[34,234,44],{},"の完了より先に",[34,237,238],{},"loadProfile()","が呼ばれても、",[34,241,36],{},"が解決されてから後続の処理が実行されます。",[39,244,246,248],{"id":245},"liff-ready-never-rejects",[34,247,36],{},"は「成功」しか通知しない",[26,250,251,252,254],{},"ここからが本題です。『LIFF APIリファレンス』の「",[30,253,36],{"href":32},"」には次のように書かれています。",[256,257,258],"blockquote",{},[26,259,260,262,263,265,266,269],{},[34,261,44],{},"実行中に何か問題が起きても、",[34,264,36],{},"はrejectしません。また、",[34,267,268],{},"LiffError","オブジェクトを返すこともありません。",[26,271,272,273,275,276,278,279,283,284,286,287,290,291,293,294,296],{},"つまり、LIFF IDの設定ミスやネットワークエラーで",[34,274,44],{},"が失敗すると、",[34,277,36],{},"はrejectされるのではなく、",[280,281,282],"strong",{},"いつまでも解決されないまま残ります","。先ほどの",[34,285,238],{},"でいえば、",[34,288,289],{},"await liff.ready","の先には進みません。このとき",[34,292,36],{},"側にはエラーが通知されないため、エラー処理を",[34,295,36],{},"に期待していると、「画面が表示されないが、コンソールにもそれらしいエラーがない」という状況になり、原因に気づきにくくなります。",[26,298,299,301,302,304,305,307,308,310,311,314,315,317,318,321,322,324],{},[34,300,36],{},"は「",[34,303,44],{},"が完了したか」だけを伝えるシンプルな完了シグナルで、エラーハンドリングの責務は持っていません。エラー処理は",[34,306,44],{},"が返すPromiseの側で行ってください。最初のコード例で、エントリポイントの",[34,309,44],{},"に",[34,312,313],{},".catch(handleInitError)","を付けていたのはこのためです。初期化の失敗は、この",[34,316,146],{},"にしか通知されません。",[34,319,320],{},"handleInitError","でエラー画面への切り替えなどを行っておけば、",[34,323,36],{},"を待つ側が止まったままでも、ユーザーに何も表示されないという事態を避けることができます。",[26,326,327],{},"役割分担は以下のとおりです。",[329,330,331,344],"table",{},[332,333,334],"thead",{},[335,336,337,341],"tr",{},[338,339,340],"th",{},"やりたいこと",[338,342,343],{},"使うもの",[345,346,347,359],"tbody",{},[335,348,349,355],{},[350,351,352,354],"td",{},[34,353,44],{},"の完了を任意の場所で待つ",[350,356,357],{},[34,358,36],{},[335,360,361,366],{},[350,362,363,365],{},[34,364,44],{},"の失敗をハンドリングする",[350,367,368,370,371],{},[34,369,44],{},"が返すPromiseの",[34,372,146],{},[26,374,375,376,378,379,381,382,384,385,387,388,390],{},"なお、「",[34,377,44],{},"の完了を待つ場所」で失敗も知りたい場合は、",[34,380,36],{},"ではなく",[34,383,44],{},"が返すPromiseを共有してawaitしてください。こちらは失敗時にrejectされます。また、アプリの状態管理に",[34,386,44],{},"の成否を載せる方法もあります。失敗のハンドリングが各所で必要なアプリでは、最初からPromiseを共有する設計のほうが向いています。",[34,389,36],{},"はあくまで「成功だけを手軽に待つ」ためのプロパティです。",[39,392,394],{"id":393},"pluggable-sdk","プラガブルSDKでもそのまま利用できます",[26,396,397,401,402,406,407,410],{},[30,398,399],{"href":32},[34,400,36],{},"はSDKのコアに含まれているため、バンドルサイズ削減のために",[30,403,405],{"href":404},"\u002Fdocs\u002Fliff\u002Fpluggable-sdk\u002F","プラガブルSDK","（",[34,408,409],{},"@line\u002Fliff\u002Fcore","）を使っている場合でも、追加モジュールなしでそのまま利用できます。",[39,412,414],{"id":413},"wrap-up","まとめ",[416,417,418,427,438],"ul",{},[419,420,421,423,424,426],"li",{},[34,422,36],{},"を使うと、",[34,425,44],{},"の完了を自前の配線なしで手軽に待つことができます。",[419,428,429,430,432,433,370,435,437],{},"ただし、",[34,431,36],{},"は失敗を通知しません。エラー処理は",[34,434,44],{},[34,436,146],{},"で行ってください。",[419,439,440,441,443],{},"待つ場所で失敗も知りたい場合は、",[34,442,44],{},"が返すPromiseを共有するか、アプリの状態管理に成否を載せる方法を検討してください。",[26,445,446,447,449],{},"詳しくは、『LIFF APIリファレンス』の「",[30,448,36],{"href":32},"」を参照してください。",[451,452,453],"style",{},"html pre.shiki code .sH3jZ, html code.shiki .sH3jZ{--shiki-default:#8B949E}html pre.shiki code .sZEs4, html code.shiki .sZEs4{--shiki-default:#E6EDF3}html pre.shiki code .sc3cj, html code.shiki .sc3cj{--shiki-default:#D2A8FF}html pre.shiki code .s9uIt, html code.shiki .s9uIt{--shiki-default:#A5D6FF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .suJrU, html code.shiki .suJrU{--shiki-default:#FF7B72}html pre.shiki code .sFSAA, html code.shiki .sFSAA{--shiki-default:#79C0FF}",[455,456],"tags",{"tags":231,"lang":457,"section":458},"en","tips",{"title":15,"searchDepth":186,"depth":211,"links":460},[461,464,467,470,473],{"id":462,"depth":125,"text":463},"liffinitの完了をどこで待つか-where-to-await-init","liff.init()の完了をどこで待つか {#where-to-await-init}",{"id":465,"depth":125,"text":466},"liffreadyでliffinitの呼ぶ場所と待つ場所を分離する-decouple-with-liff-ready","liff.readyでliff.init()の「呼ぶ場所」と「待つ場所」を分離する {#decouple-with-liff-ready}",{"id":468,"depth":125,"text":469},"liffreadyは成功しか通知しない-liff-ready-never-rejects","liff.readyは「成功」しか通知しない {#liff-ready-never-rejects}",{"id":471,"depth":125,"text":472},"プラガブルsdkでもそのまま利用できます-pluggable-sdk","プラガブルSDKでもそのまま利用できます {#pluggable-sdk}",{"id":474,"depth":125,"text":475},"まとめ-wrap-up","まとめ {#wrap-up}","今回のTipsでは、地味ながら便利なプロパティliff.readyと、その使い方の注意点を紹介します。","md",{"date":479,"tags":231,"locale":480,"sidebar":481},"2026-07-30 00:00 UTC","ja",false,true,"\u002Fja\u002Ftips\u002F2026\u002F07\u002F30\u002Fliff-ready",{"title":5,"description":476},"ja\u002Ftips\u002F2026\u002F07\u002F30\u002Fliff-ready","YxDa_C5ewkjResXoPENiLmzFTlYXtmp4NIk-aYiWpQQ",{"id":4,"title":5,"body":488,"description":476,"extension":477,"meta":783,"navigation":482,"path":483,"seo":784,"stem":485,"__hash__":486},{"type":7,"value":489,"toc":776},[490],[10,491,492,496,498,504,508,522,530,536,548,572,622,634,638,642,652,668,686,688,722,734,736,746,748,768,772,774],{},[13,493,494],{"id":15,"class":16},[18,495],{},[21,497],{"date":23,"class":24},[26,499,28,500,37],{},[30,501,502],{"href":32},[34,503,36],{},[39,505,506,45],{"id":41},[34,507,44],{},[26,509,48,510,55,514,61,518,65,520,68],{},[30,511,512],{"href":51},[34,513,54],{},[30,515,516],{"href":58},[34,517,44],{},[34,519,64],{},[34,521,44],{},[26,523,71,524,74,526,79],{},[34,525,44],{},[30,527,528],{"href":32},[34,529,36],{},[39,531,532,85,534,88],{"id":82},[34,533,36],{},[34,535,44],{},[26,537,538,93,540,96,542,99,544,102,546,105],{},[34,539,36],{},[34,541,44],{},[34,543,44],{},[34,545,44],{},[34,547,36],{},[107,549,550],{"className":109,"code":110,"language":111,"meta":15,"style":15},[34,551,552,556],{"__ignoreMap":15},[115,553,554],{"class":117,"line":118},[115,555,122],{"class":121},[115,557,558,560,562,564,566,568,570],{"class":117,"line":125},[115,559,129],{"class":128},[115,561,133],{"class":132},[115,563,136],{"class":128},[115,565,140],{"class":139},[115,567,143],{"class":128},[115,569,146],{"class":132},[115,571,149],{"class":128},[107,573,574],{"className":109,"code":152,"language":111,"meta":15,"style":15},[34,575,576,580,590,596,612,618],{"__ignoreMap":15},[115,577,578],{"class":117,"line":118},[115,579,159],{"class":121},[115,581,582,584,586,588],{"class":117,"line":125},[115,583,165],{"class":164},[115,585,168],{"class":164},[115,587,171],{"class":132},[115,589,174],{"class":128},[115,591,592,594],{"class":117,"line":177},[115,593,180],{"class":164},[115,595,183],{"class":128},[115,597,598,600,602,604,606,608,610],{"class":117,"line":186},[115,599,189],{"class":164},[115,601,193],{"class":192},[115,603,196],{"class":164},[115,605,199],{"class":164},[115,607,202],{"class":128},[115,609,205],{"class":132},[115,611,208],{"class":128},[115,613,614,616],{"class":117,"line":211},[115,615,214],{"class":132},[115,617,217],{"class":128},[115,619,620],{"class":117,"line":220},[115,621,223],{"class":128},[26,623,624,228,626,232,628,235,630,239,632,242],{},[34,625,36],{},[34,627,231],{},[34,629,44],{},[34,631,238],{},[34,633,36],{},[39,635,636,248],{"id":245},[34,637,36],{},[26,639,251,640,254],{},[30,641,36],{"href":32},[256,643,644],{},[26,645,646,262,648,265,650,269],{},[34,647,44],{},[34,649,36],{},[34,651,268],{},[26,653,272,654,275,656,278,658,283,660,286,662,290,664,293,666,296],{},[34,655,44],{},[34,657,36],{},[280,659,282],{},[34,661,238],{},[34,663,289],{},[34,665,36],{},[34,667,36],{},[26,669,670,301,672,304,674,307,676,310,678,314,680,317,682,321,684,324],{},[34,671,36],{},[34,673,44],{},[34,675,44],{},[34,677,44],{},[34,679,313],{},[34,681,146],{},[34,683,320],{},[34,685,36],{},[26,687,327],{},[329,689,690,698],{},[332,691,692],{},[335,693,694,696],{},[338,695,340],{},[338,697,343],{},[345,699,700,710],{},[335,701,702,706],{},[350,703,704,354],{},[34,705,44],{},[350,707,708],{},[34,709,36],{},[335,711,712,716],{},[350,713,714,365],{},[34,715,44],{},[350,717,718,370,720],{},[34,719,44],{},[34,721,146],{},[26,723,375,724,378,726,381,728,384,730,387,732,390],{},[34,725,44],{},[34,727,36],{},[34,729,44],{},[34,731,44],{},[34,733,36],{},[39,735,394],{"id":393},[26,737,738,401,742,406,744,410],{},[30,739,740],{"href":32},[34,741,36],{},[30,743,405],{"href":404},[34,745,409],{},[39,747,414],{"id":413},[416,749,750,756,764],{},[419,751,752,423,754,426],{},[34,753,36],{},[34,755,44],{},[419,757,429,758,432,760,370,762,437],{},[34,759,36],{},[34,761,44],{},[34,763,146],{},[419,765,440,766,443],{},[34,767,44],{},[26,769,446,770,449],{},[30,771,36],{"href":32},[451,773,453],{},[455,775],{"tags":231,"lang":457,"section":458},{"title":15,"searchDepth":186,"depth":211,"links":777},[778,779,780,781,782],{"id":462,"depth":125,"text":463},{"id":465,"depth":125,"text":466},{"id":468,"depth":125,"text":469},{"id":471,"depth":125,"text":472},{"id":474,"depth":125,"text":475},{"date":479,"tags":231,"locale":480,"sidebar":481},{"title":5,"description":476},{"toc":786,"fullToc":786},[787,789,791,793,794],{"id":41,"depth":125,"text":788},"liff.init()の完了をどこで待つか",{"id":82,"depth":125,"text":790},"liff.readyでliff.init()の「呼ぶ場所」と「待つ場所」を分離する",{"id":245,"depth":125,"text":792},"liff.readyは「成功」しか通知しない",{"id":393,"depth":125,"text":394},{"id":413,"depth":125,"text":414},1786497886211]