首页 > 解决方案 > webworker-theads 中的关闭

问题描述

当我在 node.js 中研究工作线程时,我按照“webworker-threads”npm 包网站上的说明进行操作,并且我实现了以下代码略有错误。这让我重新考虑了关闭。

const express = require("express");
const app = express();
const Worker = require("webworker-threads").Worker;
app.get("/", (req, res) => {
  //   let counter = 0; // if i put this here code is not working
  const worker = new Worker(function() {
    this.onmessage = function() {
      let counter = 0;
      while (counter < 1000000) {
        counter = counter + 1;
      }
      this.postMessage(counter);
    };
  });
  worker.onmessage = function(result) {
    console.log(result);
    res.send(result);
  };
  worker.postMessage();
});
app.get("/fast", (req, res) => {
  res.send("this is fast");
});
app.listen(3100, () => {
  console.log("listening");
});

错误地我把let counter=0工作函数放在外面,但服务器挂起并且无法加载。然后我把它放在工作函数中尝试不同的东西并且它起作用了。

但是我该如何描述呢?它是否正确?

Worker 函数无法访问其闭包。

同样在这个例子中,为什么不允许工作函数访问它的闭包?因为只有一个函数想要访问 let counter=0

标签: javascriptnode.jsclosures

解决方案


1. 面向对象编程的替代方案

理论上,任何可以使用类/构造函数的地方都可以使用闭包。它们本质上都执行相同的操作:封装数据并维护状态 - 但通过不同的机制。对象使用上下文来维护状态(Java 将其称为“作用域”,但因为 Java 实际上没有真正的作用域),而闭包使用作用域来维护状态。

闭包对于替换单方法类特别有​​用(令人惊讶的是,它有很多用途):

让我们看一个简单的文件记录器。OO 实现可以是:

class Logger {
    constructor (filename) {
        this.logfile = fs.openSync(filename,'a');
        this.log.bind(this);
    }

    log (txt) {
        const now = new Date().toISOString();
        fs.write(this.logfile, `${now} : ${txt}\n`);
    }
}

// usage:
const logger = new Logger('file.log');
logger.log('Hello');

可以使用闭包来实现相同的逻辑:

function makeLogger (filename) {
    const logfile = fs.openSync(filename,'a');

    return function (txt) {
        const now = new Date().toISOString();
        fs.write(logfile, `${now} : ${txt}\n`); // <-- using closure here!
    }
}

// usage:
const log = makeLogger('file.log');
log('Hello');

根据您与谁交谈,闭包实现更易于阅读(我是对闭包比对类更满意的人之一)。它不仅更短,而且状态也被包含在内,并且不能从其他代码中更改。

2. 通常在任何需要新作用域的地方(需要隐藏一些东西)

由于函数是操作范围的唯一机制,因此您还需要使用闭包来创建范围。这在安全关键代码中特别有用,例如处理需要与 3rd 方库交互的身份验证和金融交易的代码。

2.1。节点模块

Node.js 专门使用闭包来实现 javascript 中不存在的东西:文件范围。

node 中的模块被加载到 IIFE 中,从而创建了一个闭包。模块文件中的所有变量对文件中定义的所有函数(闭包)都是可见的,但对其他模块不可见(除非声明时没有var,letconst)。Ryan Dahl 不想将 Javascript 作为一种语言进行修改,而只是在该语言之上添加一个框架以使其在浏览器之外有用。幸运的是,Javascript 足够强大(有闭包),这是可能的。

现实世界的例子

有几个大规模使用闭包的真实例子:

  • React.FunctionComponent是 React.js 中的一项最新功能,它允许用户使用闭包来实现 React 组件而不是类。这通常会减少代码行数和复杂性(是的,这与前端更相关,但规模非常大)

  • async.js大量使用闭包来跟踪异步操作

  • Express.js是混合的。虽然大部分代码都是面向对象的,但它也使用闭包,尤其是在中间件/路由架构中。


推荐阅读