簡體   English   中英

帶有fork的異步Express處理程序

[英]Asynchronous express handlers with fork

考慮以下快遞程序

const express = require("express");
const { fork } = require('child_process');

const API_PORT = 3001

const app = express()
app.listen(API_PORT, () => console.log(`Listening on port ${API_PORT}`));

app.get("/", async (_req, res) => {
    var compute = fork("child.js")
    compute.send('start');
    compute.on("message", result => {
        res.send(result)
    })
})

它是附帶的child.js文件:

process.on("message", (msg) => {
    var date1 = new Date();
    var start_sec = date1.getSeconds();

    setTimeout(() => {
        var date2 = new Date();
        var fin_sec = date2.getSeconds();
        process.send("Starting at: " + start_sec + " / Finished at: " + fin_sec);
    }, 5000);
});

當我快速依次打開兩個瀏覽器到localhost:3001/ ,我希望它們都將在5秒鍾后返回。 例如,如果我在時間= 13時打開一個瀏覽器,而在時間= 14時打開第二個瀏覽器,則我希望瀏覽器分別顯示Starting at 13 / Finished at 18Starting at 14 / finished at 19 而是顯示Starting at 13 / Finished at 18Starting at 18 / Finished at 23

為什么第二個請求等待第一個請求完成? 我將如何修改此代碼以獲得預期的結果?

您的代碼很好,我設法在2個firefox選項卡上Starting at: 54 / Finished at: 59以下位置Starting at: 53 / Finished at: 58 Starting at: 54 / Finished at: 59

但是,如果您使用2個chrome瀏覽器執行此操作,則第二個chrome標簽會等待第一個chrome瀏覽器完成。 我不知道確切的解釋,但這就是Chrome處理多選項卡請求的方式。

這是Chrome特有的“功能”。 如果您將兩個相同的請求發送到同一主機,Chrome會將第二個請求排隊,直到第一個請求響應為止。 其他瀏覽器(例如Firefox)則不這樣做。 大概有人認為,通過等待第一個請求完成,他們可以防止不必要的服務器過載。

您可以通過支持多個執行相同操作的路由,然后為第一個和第二個請求使用單獨的路由(例如/1/2 您可以在路徑上嘗試使用查詢參數,看看如果查詢參數不同(例如/?a=1/?a=2 Chrome瀏覽器是否會繞過該功能。


在運行我自己的測試時,查詢參數似乎足以滿足對Chrome瀏覽器的請求,從而避免了排隊並讓它們並行運行。

我確認了這兩個URL的問題:

http://localhost:3001/
http://localhost:3001/

我避免了以下兩個URL的問題:

http://localhost:3001/?a=1
http://localhost:3001/?a=2

這種行為是由express引起的。 如果在fork之前添加一些console.log ,您將看到請求被阻止,直到將響應發送到客戶端為止。

app.get("/", (req, res) => {
  console.log('A');
  var compute = fork("child.js")
  compute.send('start');
  compute.on("message", result => {
    res.send(result)
  })
})

您將看到一個A,然后響應出現在瀏覽器1中,然后您將獲得針對瀏覽器2的A。

為了實現您的目標,您需要建立websocket連接,或使用服務器推送到客戶端

如果您將代碼更改為此

app.get("/", (req, res) => {
  var compute = fork("child.js")
  compute.send('start');
  compute.on("message", result => {
    console.log(result)
  })
  res.status(200).send('OK')
})

您將在控制台中看到自己想要的輸出。

Starting at: 36 / Finished at: 39
Starting at: 38 / Finished at: 41


但是同樣,在快速HTTP中,您無法第二次將響應發送到客戶端。

app.get("/", (req, res) => {
  var compute = fork("child.js")
  compute.send('start');
  compute.on("message", result => {
    res.send(result) // Won't work!!!
  })
  res.status(200).send('OK')
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM