UNPKG

narou

Version:
1 lines 4.78 kB
{"version":3,"sources":["../../src/util/jsonp.ts"],"sourcesContent":["/**\n * MIT license\n */\n\n// Callback index.\nlet count = 0;\n\ntype CallbackId<Prefix extends string = string> = `${Prefix}${number}`;\n\ndeclare global {\n interface Window {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: CallbackId]: (data: any) => void;\n }\n}\n\n/**\n * JSONP呼び出しのオプション設定\n */\nexport type JsonpOption = {\n /**\n * コールバック関数名のプレフィックス\n * @default \"__jp\"\n */\n prefix?: string;\n \n /**\n * コールバック関数名を指定するURLパラメータ名\n * @default \"callback\"\n */\n param?: string;\n \n /**\n * タイムアウト時間(ミリ秒)\n * @default 15000\n */\n timeout?: number;\n};\n\nconst noop = function () { };\n\n/**\n * JSONPリクエストを実行してデータを取得します。\n * \n * @param url - リクエスト先のURL\n * @param options - JSONP呼び出しのオプション設定\n * @returns JSONPリクエストの結果をPromiseで返します\n * @throws {Error} タイムアウトが発生した場合、\"Timeout\"メッセージのエラーをスローします\n * \n * @example\n * ```typescript\n * // 基本的な使用方法\n * const data = await jsonp<ResponseType>('https://example.com/api');\n * \n * // オプション指定\n * const data = await jsonp<ResponseType>('https://example.com/api', {\n * prefix: 'customPrefix',\n * param: 'callbackParam',\n * timeout: 10000\n * });\n * ```\n */\nexport function jsonp<T>(\n url: string,\n { prefix = \"__jp\", param = \"callback\", timeout = 15000 }: JsonpOption = {}\n): Promise<T> {\n return new Promise(function (resolve, reject) {\n // 最初のscriptタグを取得し、そのタグの直前に新しいscriptタグを挿入するための参照を取得\n // これにより、ページの構造を大きく変えることなくscriptを追加できる\n const targetChild = document.getElementsByTagName(\"script\").item(0);\n const target = targetChild?.parentNode ?? document.head;\n\n // ユニークなコールバック関数名を生成\n const id: CallbackId = `${prefix}${count++}`;\n \n // リソース解放用の関数を定義\n // スクリプトタグの削除、コールバック関数のクリーンアップ、タイマーのクリアを行う\n const cleanup = function () {\n // Remove the script tag.\n if (script && script.parentNode) {\n script.parentNode.removeChild(script);\n }\n\n // コールバック関数を空の関数に置き換えてメモリリークを防止\n window[id] = noop;\n\n if (timer) {\n clearTimeout(timer);\n }\n };\n\n // タイムアウト処理の設定\n // 指定された時間内にレスポンスがない場合はエラーとして処理\n const timer =\n timeout > 0\n ? setTimeout(() => {\n cleanup();\n reject(new Error(\"Timeout\"));\n }, timeout)\n : undefined;\n\n // サーバーからのレスポンスを処理するコールバック関数\n const callback = (data: T) => {\n cleanup();\n resolve(data);\n };\n \n // グローバルスコープにコールバック関数を登録\n // これによりJSONPのレスポンスから関数が呼び出せるようになる\n window[id] = callback;\n\n // JSONPリクエスト用のscriptタグを作成\n const script = document.createElement(\"script\");\n const urlObj = new URL(url);\n \n // URLにコールバック関数名をパラメータとして追加\n urlObj.searchParams.set(param, id);\n script.setAttribute(\"src\", urlObj.toString());\n \n // DOMにscriptタグを挿入し、リクエストを開始\n target.insertBefore(script, targetChild);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAKA,IAAI,QAAQ;AAkCZ,IAAM,OAAO,WAAY;AAAE;AAuBpB,SAAS,MACd,KACA,EAAE,SAAS,QAAQ,QAAQ,YAAY,UAAU,KAAM,IAAiB,CAAC,GAC7D;AACZ,SAAO,IAAI,QAAQ,SAAU,SAAS,QAAQ;AAG5C,UAAM,cAAc,SAAS,qBAAqB,QAAQ,EAAE,KAAK,CAAC;AAClE,UAAM,SAAS,aAAa,cAAc,SAAS;AAGnD,UAAM,KAAiB,GAAG,MAAM,GAAG,OAAO;AAI1C,UAAM,UAAU,WAAY;AAE1B,UAAI,UAAU,OAAO,YAAY;AAC/B,eAAO,WAAW,YAAY,MAAM;AAAA,MACtC;AAGA,aAAO,EAAE,IAAI;AAEb,UAAI,OAAO;AACT,qBAAa,KAAK;AAAA,MACpB;AAAA,IACF;AAIA,UAAM,QACJ,UAAU,IACN,WAAW,MAAM;AACjB,cAAQ;AACR,aAAO,IAAI,MAAM,SAAS,CAAC;AAAA,IAC7B,GAAG,OAAO,IACR;AAGN,UAAM,WAAW,CAAC,SAAY;AAC5B,cAAQ;AACR,cAAQ,IAAI;AAAA,IACd;AAIA,WAAO,EAAE,IAAI;AAGb,UAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,UAAM,SAAS,IAAI,IAAI,GAAG;AAG1B,WAAO,aAAa,IAAI,OAAO,EAAE;AACjC,WAAO,aAAa,OAAO,OAAO,SAAS,CAAC;AAG5C,WAAO,aAAa,QAAQ,WAAW;AAAA,EACzC,CAAC;AACH;","names":[]}