节点JS服务器停止侦听直到承诺(运行循环的async函数,希望使此循环在后台运行)已解决)

发布于 2025-01-21 12:42:51 字数 736 浏览 1 评论 0原文

端口上的服务器代码

app.listen(PORT, () => {
          console.log(`Server running on ${PORT}`);
          });

是我正在收到请求的

        app.get("/",(req, res) => {
          res.header("Access-Control-Allow-Origin", "*");
          console.log("before call");
          callback(100,1000000000000).then(response=>console.log(response));
          console.log("after call");
          res.end();
        });

        async function callback(first, second) {
           await null;
           for (let i = first; i < second; i++) {
             if (isPrime(i)) {
                //writes to file if the number is prime
             }
           }

This is my server code which is listening on the port

app.listen(PORT, () => {
          console.log(`Server running on ${PORT}`);
          });

Here I am receiving a request and sending it to the function to process

        app.get("/",(req, res) => {
          res.header("Access-Control-Allow-Origin", "*");
          console.log("before call");
          callback(100,1000000000000).then(response=>console.log(response));
          console.log("after call");
          res.end();
        });

This is the function that is processing incoming request

        async function callback(first, second) {
           await null;
           for (let i = first; i < second; i++) {
             if (isPrime(i)) {
                //writes to file if the number is prime
             }
           }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

幸福丶如此 2025-01-28 12:42:51

node.js在一个线程上执行大多数操作,主线程,但是可以通过产卵子进程或使用worker来使用多个线程。线程。您可以阅读有关Worker线程子进程的很多信息:文档:
https://nodejs.org/api/worker_thread/worker_threads.html
https://nodejs.org/api/api/api/child/child_process.html_process.html#child-child-process
Worker线程在像您这样的方案中特别有用,在您的情况下,您要执行繁重的同步任务,并且您不希望它们阻止Main Tread。如果您具有异步I/ O的任务,例如文件读取/写作,它们具有同步和异步API等……最好使用内置的异步方法,因为它们是性能更高。

Worker线程,例如儿童进程主线程通过Events消息的形式侦听器
我在这里给您一个示例,这是一个简单的节点Web服务器,当它收到请求时,它将重生Worker线程并将其发送给带有两个nubmess的消息类型。从现在开始,主线程保持免费,所有计算都在工作线程上执行。当Worker线程已经完成了计算所有质数并将其写入文件时,它会通知主线程,主线程终止了工作。与您的情况的不同之处在于,在这种情况下,主线程不会被阻止,而其他客户请求可能会像往常一样通过处理:

// App.js

const { Worker } = require("worker_threads");
const http = require("http");

const hostname = "127.0.0.1";
const port = 5001;

const server = http.createServer(serverHandler);

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

function serverHandler(req, res) {
  try {
    const worker = new Worker("./worker-thread.js"); // Respawn a worker
    console.log("BEFORE HEAVY WORK");
    worker.on("message", (result) => {
      console.log(`Message received in parent thread : ${result.message}`);
      if (result.message === "SUCCESS") {
        console.log("WORKER RESULT:", result.message);
        worker.terminate();
      }
    });
    worker.on("exit", (code) => {
      console.log(`worker exited with code ${code}`);
    });
    worker.postMessage({
      type: "calculate_primes",
      payload: { first: 1, second: 100000 },
    });
    console.log("MAIN THREAD REMAINED FREE");
    res.end("Your request is being processed correctly");
  } catch (e) {
    console.log(e);
  }
}

这是“ worker-thread.js”文件:

const { parentPort } = require("worker_threads");
const fs = require("fs");

function calculatePrime({ first, second }) {
  console.log("First number:", first, "Second number:", second);
  const stream = fs.createWriteStream("result.txt", { flags: "a" });
  const result = [];
  for (let i = first; i < second; i++) {
    if (isPrime(i)) {
      result.push(i);
    }
  }
  stream.write(JSON.stringify(result));

  return stream.end();
}

parentPort.on("message", (message) => {
  try {
    console.log("MESSAGE RECEIVED ON WORKER THREAD", message);
    if (message.type === "calculate_primes") {
      console.log("STARTING HEAVY WORK ON WORKER THREAD");
      // CPU HEAVY TASK
      calculatePrime(message.payload);
      // SEND CONFIRM MESSAGE BACK TO MAIN THREAD WHEN FINISHED
      parentPort.postMessage({ message: "SUCCESS" });
    }
  } catch (e) {
    console.log(e);
  }
});

function isPrime(num) {
  for (let i = 2; i < num; i++) if (num % i === 0) return false;
  return num > 1;
}

仅通过执行app.js ,然后在Web浏览器上转到127:0.0.1:5001。您应该在半秒之内收到响应,但是工人将继续处理您的iSprime循环,并将写入结果。

Node.js executes most of the operations on one thread, the main thread, but it can use multiple threads, by spawning child processes, or by using the worker thread. You can read a lot about worker thread and child processes on docs:
https://nodejs.org/api/worker_threads.html
https://nodejs.org/api/child_process.html#child-process
A worker thread is particularly useful in scenarios like yours, where you have heavy synchronous tasks to be executed and you don't want them to block the main thread. If you have async I/O tasks like file reading/ writing, which have both sync and async API etc... it's better using the built-in async methods, since they are more performant.

Worker threads, like child processes communicate with the main thread the usual node way, through events that are emitted in the form of messages, and listeners.
I'll give you an example here, this is a simple Node web server, when it receives a request, it will respawn a worker thread and send it a message with two numbers and a type. From now on the main thread remains free, and all the computation is performed on the worker thread. When the worker thread has done to compute all prime numbers and write them in a file, it notifies the main thread, and the main thread terminates the worker. The difference with your case, is that in this case the main thread is not blocked, and other client requests may by processed as usual in the meanwhile:

// App.js

const { Worker } = require("worker_threads");
const http = require("http");

const hostname = "127.0.0.1";
const port = 5001;

const server = http.createServer(serverHandler);

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

function serverHandler(req, res) {
  try {
    const worker = new Worker("./worker-thread.js"); // Respawn a worker
    console.log("BEFORE HEAVY WORK");
    worker.on("message", (result) => {
      console.log(`Message received in parent thread : ${result.message}`);
      if (result.message === "SUCCESS") {
        console.log("WORKER RESULT:", result.message);
        worker.terminate();
      }
    });
    worker.on("exit", (code) => {
      console.log(`worker exited with code ${code}`);
    });
    worker.postMessage({
      type: "calculate_primes",
      payload: { first: 1, second: 100000 },
    });
    console.log("MAIN THREAD REMAINED FREE");
    res.end("Your request is being processed correctly");
  } catch (e) {
    console.log(e);
  }
}

This is the "worker-thread.js" file:

const { parentPort } = require("worker_threads");
const fs = require("fs");

function calculatePrime({ first, second }) {
  console.log("First number:", first, "Second number:", second);
  const stream = fs.createWriteStream("result.txt", { flags: "a" });
  const result = [];
  for (let i = first; i < second; i++) {
    if (isPrime(i)) {
      result.push(i);
    }
  }
  stream.write(JSON.stringify(result));

  return stream.end();
}

parentPort.on("message", (message) => {
  try {
    console.log("MESSAGE RECEIVED ON WORKER THREAD", message);
    if (message.type === "calculate_primes") {
      console.log("STARTING HEAVY WORK ON WORKER THREAD");
      // CPU HEAVY TASK
      calculatePrime(message.payload);
      // SEND CONFIRM MESSAGE BACK TO MAIN THREAD WHEN FINISHED
      parentPort.postMessage({ message: "SUCCESS" });
    }
  } catch (e) {
    console.log(e);
  }
});

function isPrime(num) {
  for (let i = 2; i < num; i++) if (num % i === 0) return false;
  return num > 1;
}

Test it just by executing App.js and going to 127:0.0.1:5001 on your web browser. You should receive the response within half a second, but the worker will keep processing your isPrime loop and will write to result.txt the result when done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文