当前位置: 首页 > 知识库问答 >
问题:

如何处理树震动代码中的副作用?

潘俊楚
2023-03-14

我一直试图学习如何编写树摇动友好的代码,但遇到了一个不可避免的副作用的问题,我不知道如何处理。

在我的一个模块中,我访问全局Audio构造函数,并使用它来确定浏览器可以播放哪些音频文件(类似于现代的方式)。每当我尝试树形摇动我的代码时,Audio元素和对它的所有引用都不会被删除,即使我没有在我的文件中导入模块。

let audio = new Audio(); // or document.createElement('audio')
let canPlay = {
  ogg: audio.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '');
  mp3: audio.canPlayType('audio/mpeg; codecs="mp3"').replace(/^no$/, '');
  // ...
};

我知道包含副作用的代码无法消除,但我找不到的是如何处理不可避免的副作用。我不能不访问全局对象来创建检测功能支持所需的audio元素。那么,我如何处理访问全局浏览器函数/对象(我在这个库中经常这样做)的方式,使其对树摇动友好,并且仍然允许我消除代码?

共有2个答案

孔理
2023-03-14

您可以实现一个模块来为您提供与您的问题所建议的类似的使用模式,使用音频()来访问音频对象,并且canPlay,而无需函数调用。这可以通过在函数中运行Audio构造函数来实现,正如Asad所建议的那样,然后在每次希望访问该函数时调用该函数。对于canPlay,我们可以使用代理,允许数组索引作为函数在引擎盖下实现。

假设我们创建了一个文件audio.js

let audio = () => new Audio();
let canPlay = new Proxy({}, {
    get: (target, name) => {
        switch(name) {
            case 'ogg':
                return audio().canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '');
            case 'mp3':
                return audio().canPlayType('audio/mpeg; codecs="mp3"').replace(/^no$/, '');
        }
    }
});

export {audio, canPlay}

这些是在各种index.js文件上运行的结果,rollup index.js-f iife

import {} from './audio';
(function () {
    'use strict';



}());
import {audio} from './audio';

console.log(audio());
(function () {
    'use strict';

    let audio = () => new Audio();

    console.log(audio());

}());
import {canPlay} from './audio';

console.log(canPlay['ogg']);
(function () {
    'use strict';

    let audio = () => new Audio();
    let canPlay = new Proxy({}, {
        get: (target, name) => {
            switch(name) {
                case 'ogg':
                    return audio().canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '');
                case 'mp3':
                    return audio().canPlayType('audio/mpeg; codecs="mp3"').replace(/^no$/, '');
            }
        }
    });

    console.log(canPlay['ogg']);

}());

此外,如果您希望保留问题中概述的属性,则无法按最初的意图实现音频。其他短的可能性音频()音频音频(如这里所示:调用一个没有括号的函数),这可以被认为是更令人困惑的。

最后,其他不涉及数组索引或函数调用的全局变量必须以类似于let audio=()=

乐正浩博
2023-03-14

您可以从Haskell/PureScript的书中翻出一页,简单地限制自己在导入模块时不会产生任何副作用。相反,您可以导出表示副作用的thunk,例如访问用户浏览器中的全局音频元素,并将其他函数/值参数化为该thunk生成的值。

下面是代码片段的外观:

// :: type IO a = () -!-> a

// :: IO Audio
let getAudio = () => new Audio();

// :: Audio -> { [MimeType]: Boolean }
let canPlay = audio => {
  ogg: audio.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/, '');
  mp3: audio.canPlayType('audio/mpeg; codecs="mp3"').replace(/^no$/, '');
  // ...
};

然后在主模块中,您可以使用适当的thunk来实例化实际需要的全局变量,并将它们插入使用它们的参数化函数/值中。

很明显,如何手动插入所有这些新参数,但可能会变得单调乏味。有几种技术可以缓解这种情况;您可以再次从Haskell/PureScript中窃取一种方法,即使用读取器monad,这有助于为包含简单函数的程序注入依赖关系。

关于阅读器monad的更详细的解释以及如何使用它来贯穿整个程序的上下文超出了这个答案的范围,但是这里有一些链接,你可以在这里阅读这些东西:

    null

(免责声明:我没有彻底阅读或审查所有这些链接,我只是在谷歌上搜索关键词并复制了一些介绍看起来很有希望的链接)

 类似资料:
  • 我已经挣扎了几个小时想找到解决这个问题的办法... 我正在开发一个在线记分牌的游戏。玩家可以随时登录和退出。完成一场比赛后,玩家会看到记分牌,看到自己的排名,分数会自动提交。 记分牌显示球员的排名,排行榜。 记分牌在用户完成游戏(提交分数)和用户只想查看他们的排名时都使用。 这就是逻辑变得非常复杂的地方: > 如果用户已经登录,那么分数将首先提交。保存新记录后,记分牌将被加载。 用户可以随时登录和

  • 虽然我按照文档中解释的步骤(参见此处)启用了树抖动,但它似乎没有任何效果。我将与

  • 冲突合并一般是因为自己的本地做的提交和服务器上的提交有差异,并且这些差异中的文件改动,Git不能自动合并,那么就需要用户手动进行合并 如我这边执行git pull origin master 如果Git能够自动合并,那么过程看起来是这样的 拉取的时候,Git自动合并,并产生了一次提交。 如果Git不能够自动合并,那么会提示 这个时候我们就可以知道README.MD有冲突,需要我们手动解决,修改RE

  • 本文向大家介绍Android震动与提示音实现代码,包括了Android震动与提示音实现代码的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了android消息提示的具体代码,供大家参考,具体内容如下 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。

  • 不知道为什么摇树没有像我预期的那样有效。。。我的目标是建立一个

  • 问题内容: 我面对的是153个字符长的特定行。现在,我倾向于在120个字符后断开字符(当然,这在很大程度上取决于我所在的位置和当地的约定。)但是,老实说,我在任何地方断开该行都会使它看起来很糟。因此,我正在寻找一些有关该怎么做的想法。 这是一行: 我对如何/在何处打破界限(以及为什么)以及缩短界限本身的想法持开放态度。 我们不是Java商店,也没有针对此类事情的本地约定,或者显然我会简单地遵循它们