美文网首页
微信小程序setTimeout参数问题

微信小程序setTimeout参数问题

作者: 吴晗君 | 来源:发表于2019-05-14 09:36 被阅读0次

    起因

    今天一个小程序客户接入我们的第三方js,没有正常执行,而我们自测是可以的。刚开始测试调节版本库发现大于等于1.9.2的就可以正常执行,低的就有问题。

    debug

    晚上在自己的环境上解除代码混淆,调试了一下发现是Promise的问题。

    Promise.resolve(x).then(() => {
      console.log(‘这里没有执行’)
    })
    

    看了下代码,由于项目中用到了defer对象,所以Promise是用的第三方而不是原生的。而该第三方Promise实现用到了setImmediate。webpack打包时,监测到代码中使用了setImmediate,就会自动加入setImmediate polifill实现。该setImmediate实现在一系列降级中回退到了setTimeout,并且用到了setTimeout的第三个参数,下面是使用setTimeout第三个参数的例子

    setTimeout((x) => {
      console.log(x)
    }, 1000, '默认参数1')
    

    在微信基础库版本1.9.2之前,这个参数没有被按标准实现。导致Promise出现异常。

    解决方法

    所以,最简单的方法就是在第三方Promise实现中去掉setImmediate的判断,直接用setTimeout(fn, 0)

    或者,我们可以在webpack配置中,使用下面配置来关闭自动注入的setImmediate

    {
    ...
    node: false
    }
    

    或者,直接用微信原生的Promise,实现一个defer就可以了。

      Promise.defer = function () {
        const deferred = {}
    
        deferred.promise = new Promise(function (resolve, reject) {
          deferred.resolve = resolve
          deferred.reject = reject
        })
    
        return deferred
      }
    

    总结

    最后,可以学习下webpacksetImmediate实现,依次降级用到了Process.nextTick(micro)、postMessage(macro)、MessageChannel(macro)、script(macro)、setTimeout(macro)

        // Don't get fooled by e.g. browserify environments.
        if ({}.toString.call(global.process) === "[object process]") {
            // For Node.js before 0.9
            installNextTickImplementation();
    
        } else if (canUsePostMessage()) {
            // For non-IE10 modern browsers
            installPostMessageImplementation();
    
        } else if (global.MessageChannel) {
            // For web workers, where supported
            installMessageChannelImplementation();
    
        } else if (doc && "onreadystatechange" in doc.createElement("script")) {
            // For IE 6–8
            installReadyStateChangeImplementation();
    
        } else {
            // For older browsers
            installSetTimeoutImplementation();
        }
    
        function installNextTickImplementation() {
            registerImmediate = function(handle) {
                process.nextTick(function () { runIfPresent(handle); });
            };
        }
    
        function canUsePostMessage() {
            // The test against `importScripts` prevents this implementation from being installed inside a web worker,
            // where `global.postMessage` means something completely different and can't be used for this purpose.
            if (global.postMessage && !global.importScripts) {
                var postMessageIsAsynchronous = true;
                var oldOnMessage = global.onmessage;
                global.onmessage = function() {
                    postMessageIsAsynchronous = false;
                };
                global.postMessage("", "*");
                global.onmessage = oldOnMessage;
                return postMessageIsAsynchronous;
            }
        }
    
        function installPostMessageImplementation() {
            // Installs an event handler on `global` for the `message` event: see
            // * https://developer.mozilla.org/en/DOM/window.postMessage
            // * http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#crossDocumentMessages
    
            var messagePrefix = "setImmediate$" + Math.random() + "$";
            var onGlobalMessage = function(event) {
                if (event.source === global &&
                    typeof event.data === "string" &&
                    event.data.indexOf(messagePrefix) === 0) {
                    runIfPresent(+event.data.slice(messagePrefix.length));
                }
            };
    
            if (global.addEventListener) {
                global.addEventListener("message", onGlobalMessage, false);
            } else {
                global.attachEvent("onmessage", onGlobalMessage);
            }
    
            registerImmediate = function(handle) {
                global.postMessage(messagePrefix + handle, "*");
            };
        }
    
        function installMessageChannelImplementation() {
            var channel = new MessageChannel();
            channel.port1.onmessage = function(event) {
                var handle = event.data;
                runIfPresent(handle);
            };
    
            registerImmediate = function(handle) {
                channel.port2.postMessage(handle);
            };
        }
    
        function installReadyStateChangeImplementation() {
            var html = doc.documentElement;
            registerImmediate = function(handle) {
                // Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
                // into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
                var script = doc.createElement("script");
                script.onreadystatechange = function () {
                    runIfPresent(handle);
                    script.onreadystatechange = null;
                    html.removeChild(script);
                    script = null;
                };
                html.appendChild(script);
            };
        }
    
        function installSetTimeoutImplementation() {
            registerImmediate = function(handle) {
                setTimeout(runIfPresent, 0, handle);
            };
        }
    

    相关文章

      网友评论

          本文标题:微信小程序setTimeout参数问题

          本文链接:https://www.haomeiwen.com/subject/fefdaqtx.html