美文网首页
微信小程序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参数问题

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

  • 微信小程序笔记心得

    微信小程序问题汇总及详解《一》form表单 微信小程序问题汇总及详解《二》tab切换 微信小程序问题汇总及详解《三...

  • 【小程序】广告推广-监控转化跟踪

    微信朋友圈广告推广小程序,监控小程序内部注册转化 微信广告,数据监控方案:一、使用微信广告的参数:用户通过微信广告...

  • 微信小程序实战

    微信小程序实战 有问题可以扫码加我微信,有偿解决问题。承接小程序开发。微信小程序开发交流qq群 870222928...

  • 微信小程序学习点滴

    **微信小程序学习点滴**《一》:如何获取时间,页面跳转,传递参数 **微信小程序学习点滴**《二》:开发者工具快...

  • 微信小程序开发之-Https免费证书配置

    微信小程序开发之-Https免费证书配置 有问题可以扫码加我微信,有偿解决问题。承接小程序开发。微信小程序开发交流...

  • iOS-App跳转微信小程序

    官方接入介绍App打开微信小程序并传递参数

  • 微信小程序 navigate页面跳转问题解决方案(一)

    微信小程序之wx.navigateback往回携带参数 最近在跟着别人做小程序,在跳转的时候遇到很大的问题 ,由于...

  • 微信小程序开发之心跳动画

    微信小程序开发之心跳动画 有问题可以扫码加我微信,有偿解决问题。承接小程序开发。微信小程序开发交流qq群 8702...

  • 定时器

    参数问题 setTimeout(func|code, delay)第一个参数可以是函数名, setTimeout(...

网友评论

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

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