Help us understand the problem. What is going on with this article?

window.onerrorでエラー内容が取れない時の対応

More than 1 year has passed since last update.

window.onerrorについて

window.onerror = function (msg, file, line, column, err) {
    /*
    msg: error message
    file: file path
    line: row number
    column: column number
    err: error object
    */ 
    alert(msg + file + ':' + line);
};

window.onerrorに関数を設定しておくと、処理中catchされてないエラー、つまりUncaughtErrorの情報をここで取得することが出来ます。

"Script error. line: 0"

window.onerror = function (msg, file, line, column, err) {
    console.error(msg + file + ':' + line);
};

throw new Error('test');

この時、msgには"Uncaught Error test"が渡ることが期待されますが、何故か"Script error."が常に渡ってくる場合があります。コンソールのログには出力されますが、エラーログを送信するなどの処理を書いている場合、原因を特定できないため非常に困ります。

原因と対策

これはブラウザのSame-Origin Policyによるもので、別ドメインのjsファイルをロードした時に起こります。
解決するためにはCORSを適切に設定する必要があります

  • Access-Control-Allow-Originをヘッダに設定

    サーバー側の設定でヘッダーに

    Access-Control-Allow-Origin: [許可するURI]
    

    を追加します。全てのアクセス元に対して許可する場合は*を指定します。

  • crossorigin属性を設定

    クライアント側でscriptタグに以下のようにcrossorigin属性を追加します。

    <script type="text/javascript" src="hoge.js" crossorigin="anonymous"></script>
    

requirejsの対応

require.jsを利用してロードする場合、前述したような対応はとれません。
require.loadをoverrideする方法もありますが、あまり選びたくない方法です。
そこで調べていると既にissueがあがっていました。

https://github.com/jrburke/requirejs/issues/687

require.createNodeをoverrideして属性を追加できるようにしてくれたようです。

元のコード
require.createNode = function (config, moduleName, url) {
    var node = config.xhtml ?
    document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
    document.createElement('script');

    node.type = config.scriptType || 'text/javascript';
    node.charset = 'utf-8';
    node.async = true;
    return node;
};
crossorigin属性を追加
require.createNode = function (config, moduleName, url) {
    var node = config.xhtml ?
    document.createElementNS('http://www.w3.org/1999/xhtml', 'html:script') :
    document.createElement('script');

    node.type = config.scriptType || 'text/javascript';
    node.charset = 'utf-8';
    node.async = true;
    node.setAttribute('crossorigin', 'anonymous');
    return node;
};

これでrequirejsでロードする場合にも対応出来ました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away