无法在'Window'GoogleTagManager上执行'postMessage' [英] Failed to execute 'postMessage' on 'Window' GoogleTagManager

查看:134
本文介绍了无法在'Window'GoogleTagManager上执行'postMessage'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我得到了 postMessage无法克隆错误。它发生在大多数最新的浏览器上,如Chrome 68,Firefox 61.0,IE11,Edge。

Recently, I get this postMessage couldn't be cloned error. It is happening on most of the latest browsers like Chrome 68, Firefox 61.0, IE11, Edge.


无法执行'postMessage'on' Window': function(a){if(qe。$ a.hasOwnProperty(a))return qe。$ a [a]} 无法克隆。

堆栈跟踪是:


错误:失败在'Window'上执行'postMessage': function(a){if(qe。$ a.hasOwnProperty(a))return qe。$ a [a]} can不被克隆。

at _reportEvent(eval at(:1:35637),:94:35)

at eval(eval at(:1:35637),:55: 5)

at eval(eval at(:1:35637),:433:11)

Error: Failed to execute 'postMessage' on 'Window': function (a){if(qe.$a.hasOwnProperty(a))return qe.$a[a]} could not be cloned.
at _reportEvent (eval at (:1:35637), :94:35)
at eval (eval at (:1:35637), :55:5)
at eval (eval at (:1:35637), :433:11)

搜索通过DevTools中我的页面源显示 gtm.js 作为代码片段的来源:

Searching through the source of my page in DevTools shows gtm.js as the source of the code fragment:

的来源

我的网页上有一个Google跟踪代码管理器跟踪代码。为什么会发生这种情况?

I have a Google Tag Manager tracking code on my page. Why is this happening?

推荐答案

如果 结构化克隆算法 。该算法由 窗口使用.postMessage 即可。如果我们从 中阅读文档第一个参数的window.postMessage

This happens all the time, if something can not be duplicated by the structured clone algorithm. This algorithm is used by window.postMessage. If we read the documentation from window.postMessage for the first parameter:


消息

要发送到其他窗口的数据。使用结构化克隆算法序列化数据。

message
Data to be sent to the other window. The data is serialized using the structured clone algorithm.

然后从结构化克隆算法打开描述(参见上面的上一个链接)然后我们可以阅读:

and then open the description from structured clone algorithm (see last link above) then we can read:


结构化克隆算法是由HTML5规范定义的用于复制复杂JavaScript对象的算法。它通过 postMessage()或与 IndexedDB 存储对象时在内部使用。它通过递归输入对象来构建克隆,同时保持先前访问过的引用的映射,以避免无限遍历循环。

The structured clone algorithm is an algorithm defined by the HTML5 specification for copying complex JavaScript objects. It is used internally when transferring data to and from Workers via postMessage() or when storing objects with IndexedDB. It builds up a clone by recursing through the input object while maintaining a map of previously visited references in order to avoid infinitely traversing cycles.

没有的东西使用结构化克隆


  • 错误函数结构化克隆算法不能复制对象;尝试这样做会抛出
    DATA_CLONE_ERR 异常。

  • 尝试克隆 DOM 节点同样会抛出 DATA_CLONE_ERR 异常。

  • 不保留对象的某些参数:

  • Error and Function objects cannot be duplicated by the structured clone algorithm; attempting to do so will throw a DATA_CLONE_ERR exception.
  • Attempting to clone DOM nodes will likewise throw a DATA_CLONE_ERR exception.
  • Certain parameters of objects are not preserved:


  • RegInp lastIndex 字段>对象不会被保留。

  • 属性描述符,设置器和getter(以及类似的类似元数据的功能)不会重复。例如,如果一个对象
    使用属性描述符标记为只读,则它将是重复读写
    ,因为这是默认条件。

  • 原型链不会走路和重复。

  • The lastIndex field of RegExp objects is not preserved.
  • Property descriptors, setters, and getters (as well as similar metadata-like features) are not duplicated. For example, if an object is marked read-only using a property descriptor, it will be read-write in the duplicate, since that's the default condition.
  • The prototype chain does not get walked and duplicated.

支持类型

  • All primitive types (Note: However not symbols)
  • Boolean object
  • String object
  • Date
  • RegExp (Note: The lastIndex field is not preserved.)
  • Blob
  • File
  • FileList
  • ArrayBuffer
  • ArrayBufferView (Note: This basically means all typed arrays like Int32Array etc.)
  • ImageData
  • Array
  • Object (Note: This just includes plain objects (e.g. from object literals))
  • Map
  • Set

我用一些对象测试了它,当发生这种情况时我会向你展示以下示例...

I tested it with some objects and I can show you following examples when this is happening...

自定义功能示例

var obj = {something: function(){}};
window.postMessage(obj, '*'); // DataCloneError

原生函数示例

var obj = {something: window.alert};
window.postMessage(obj, '*'); // DataCloneError

我们将看到与本机函数相同的内容,如布尔值日期字符串 RegExp 数字数组

The same we will see with native functions like Boolean, Date, String, RegExp, Number, Array.

原生对象示例

var obj = {something: document};
window.postMessage(obj, '*'); // DataCloneError

HTML元素对象示例

var obj = {something: document.createElement('b')};
window.postMessage(obj, '*'); // DataCloneError

如果我们阅读说明,我们可以写更多的例子来自上面的结构化克隆算法,但我认为这就足够了。

We could write more examples if we read the description from The structured clone algorithm above, but I think here it is enough.

在我们的代码中,我们只能使用对象中支持的类型(参见上面的列表)。但是在我们的代码中,我们必须从这段代码中联系开发人员,并写下他们如何纠正他们的代码。对于Google跟踪代码管理器,您可以将其写入官方Google代码管理器论坛描述他们如何纠正他们的代码。

In our code we could use only supported types (see the list above) in our objects. But in not our code we have to contact the developers from this code and write them how they have to correct their code. In the case from the Google Tag Manager you could write it to the Official Google Tag Manager Forum with description how they have to correct their code.

某些浏览器的解决方法

在某些浏览器中,出于安全原因,您无法覆盖本机方法。例如, IE不允许覆盖 window.postMessage 。但其他浏览器(如Chrome)允许覆盖此方法,如下所示:

In some browsers you can not override native methods for security reasons. For example IE does not allow to override window.postMessage. But other browsers like Chrome allow to override this method like follows:

var postMessageTemp = window.postMessage;
window.postMessage = function(message, targetOrigin, transfer)
{
    postMessageTemp(JSON.parse(JSON.stringify(message)), targetOrigin, transfer)
};

但请注意窗口是一个全局对象JavaScript上下文,它不是从原型创建的。换句话说:你不能用 window.prototype.postMessage = ... 覆盖它。

But note that window is a global object of JavaScript context and it is not created from the prototype. In other words: you can not override it with window.prototype.postMessage = ....

解决方法示例

var obj = {something: window};

var postMessageTemp = window.postMessage;
window.postMessage = function(message, targetOrigin, transfer)
{
    function cloneObject(obj)
    {
        var clone = {};
        for(var i in obj)
        {
            if(typeof(obj[i]) == 'object' && obj[i] != null)
            {
                if((''+obj[i]) == '[object Window]')
                {
                    delete obj[i];
                    continue;
                }

                clone[i] = cloneObject(obj[i]);
            }
            else
                clone[i] = obj[i];
        }
        return clone;
    }

    // to avoid weird error causing by window object by JSON.stringify() execution.
    var clone = cloneObject(message);

    postMessageTemp(JSON.parse(JSON.stringify(clone)), targetOrigin, transfer)
};

window.postMessage(obj, '*');

console.log('We do not have any errors.');

如何实施此解决方法

请在Google跟踪代码管理器脚本之前的HTML页面的脚本部分中放置此覆盖 window.postMessage 功能。但更好的方法是,您可以帮助Google跟踪代码管理器中的开发人员理解并更正此错误,您可以等待更正的Google跟踪代码管理器脚本。

Please put this overriden window.postMessage function in script part in your HTML page before Google Tag Manager script. But in better way you could help the developers from Google Tag Manager to understand and to correct this error and you can wait for corrected Google Tag Manager script.

这篇关于无法在'Window'GoogleTagManager上执行'postMessage'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆