Recently, I studied the problem of slow request monitoring, and wrote a simple test code: fetch function from the web page (index.html) to obtain data from the server, and then print the request time.

function requestData() {
    let start = new Date(a); fetch("http://localhost:3000/company/basic")
        .then(res= > {
            return res.json();
        })
        .then(res= > {
            let span = new Date() - start;
            console.log("span:", span);
        });
}
requestData();
Copy the code

The server uses setTimeout to delay the return of data for 1500ms (the server uses ExpressJS).

app.get("/company/basic", (req, res) => {
    setTimeout(function() {
        res.send({ hello: "Hello Fundebug!" });
    }, 1500);
});
Copy the code

Unsurprisingly, the SPAN numbers are all slightly over 1500.

Then IT occurred to me, what if I sent multiple requests at the same time? So here’s the code:

[1.2.3].forEach(function() {
    requestData();
});
Copy the code

The result also seems to be ok. In Chrome, it looks like this:

Access Fundebug slow request monitoring tests

So happily plug in the Fundebug monitor:

<script
    src="https://js.fundebug.cn/fundebug.1.9.0.min.js"
    apikey="API-KEY"
></script>
Copy the code

And set to report requests that take longer than 2 seconds:

if ("fundebug" in window) {
    fundebug.httpTimeout = 2000;
}
Copy the code

I thought refresh the page, should not receive an error.

To my surprise, Fundebug received two slow requests reporting errors.

It’s not scientific!

Click the error details, you can see the specific error message. One request took 3018 ms and one request took 4525 ms.

That is, the first request is fine, let’s say 1500 milliseconds. Let’s put the three requested times together and see what the pattern looks like: 1500,3018,4524. They are approximated in an arithmetic sequence with a difference of 1500 milliseconds. Therefore, I suspect that the three requests are blocking one by one, rather than concurrent.

Test concurrent requests to different apis

To verify this, I changed the test to request three different API interfaces.

Server code:

app.get("/company/basic", resp);
app.get("/company/basic1", resp);
app.get("/company/basic2", resp);

function resp(req, res) {
    setTimeout(function() {
        res.send({ hello: "Hello Fundebug!" });
    }, 1500);
}
Copy the code

Web side code (requestData passes in the request URL) :

[
    "http://localhost:3000/company/basic"."http://localhost:3000/company/basic1"."http://localhost:3000/company/basic2"
].forEach(function(item) {
    requestData(item);
});
Copy the code

To get the request data, change httpTimeout to 1500.

if ("fundebug" in window) {
    fundebug.httpTimeout = 1500;
}
Copy the code

Fundebug caught three requests at 1526, 1525, and 1529.

This roughly validates the previous assumption: concurrent requests to the same API interface will be blocked, and concurrent requests to different API interfaces will be executed normally.

So why is it blocked? What is the intention? Then I will introduce you slowly.

The reason behind it

Found the answer on StackOverflow:

Yes, this behavior is due to Chrome locking the cache and waiting to see the result of one request before requesting the same resource again. The answer is to find a way to make the requests unique.

That said, Chrome is designed to do just that. For consecutive identical requests, Chrome blocks subsequent requests until the previous one completes. Determine the next step by determining the cache Settings in the Header returned by the previous request.

We can do an experiment to find out.

Cache experiment

  • The server set the cache to 2 seconds

    Configure the cache time in the server-side interface return code

    res.setHeader("Cache-Control"."public, max-age=2");
    Copy the code

  • The server is not cached

    res.setHeader(
        "Cache-Control"."private, no-cache, no-store, must-revalidate"
    );
    Copy the code

  • Chrome developer panel set Disable Cache

Final question

Why does the Google Developer Console behave differently when opened and when not opened?

There was a reason for it, and for a while this distraction succeeded in preventing me from discovering the nature of the problem. When we were developing front-end projects, code changes were expected to be reflected on the web page in real time, not affected by the browser cache, but we found that often the page was refreshed without actually fetching data from the server, just the same old information. We then configure an option to set the Disable Cache to true. In other words, caching is disabled in the development environment, so there is no problem of waiting for the first request to return and then determining the cache-control Settings in its headers. That’s why when you open the Google Developer console, the request is executed without waiting.

About Fundebug

Fundebug focuses on real-time BUG monitoring for JavaScript, wechat applets, wechat games, Alipay applets, React Native, Node.js and Java online applications. Since its official launch on November 11, 2016, Fundebug has handled over 1 billion error events in total, and paid customers include Sunshine Insurance, Walnut Programming, Lychee FM, Zhangmen 1-to-1, Weimai, Qingtuanshe and many other brand enterprises. Welcome to try it for free!

Copyright statement

Reprint please indicate the author Fundebug and this article addresses: blog.fundebug.com/2019/07/17/…