akamai / boomerang

End user oriented web performance testing and beaconing
http://akamai.github.io/boomerang/
Other
1.86k stars 292 forks source link

What event should I subscribe to to know when the fetch is complete #338

Open iwindfree opened 1 year ago

iwindfree commented 1 year ago

Hi, boomerang is very excellent javascript library. I want to add a specific value to the beacon when the ajax call is completed using the auto_xhr plugin. When using XMHHttpRequest, the following my plugin code is used. By the way, when Fetch is used, I don't know exactly what event to check when the ajax call using fetch is completed.

BOOMR.subscribe("xhr_send", function (obj) {
    if(obj !== undefined && obj instanceof XMLHttpRequest) {
          let key = (impl.ajaxSeq++).toString();
          let uuid = BOOMR.utils.generateUUID();
          impl.setAjaxId(key, uuid);
          obj.mykey = key;
          obj._onreadystatechange = obj.onreadystatechange;
          obj.onreadystatechange = function () {
              if (obj.readyState === obj.DONE) {
                  if (obj.tunaKey != undefined && obj.tunaKey != null)
                      BOOMR.addVar("gxid", impl.getAjaxId(obj.mykey));
                  impl.removeAjaxId(obj.tunaKey)
              }
              if (obj._onreadystatechange) {
                  obj._onreadystatechange();
              }
          };
    }

I would like to know if there are any solutions.

querymetrics commented 1 year ago

Hi @iwindfree , the xhr_send boomerang event is emitted right before an XHR or Fetch request is sent. I don't think there's an event for when either is finished. There's xhr_error if an error occurred but nothing for success.

I can't think of a good solution without modifying boomerang. Adding a new event shouldn't be hard.

There are really hacky ways using Proxy and such if you know the internals. eg. resource.timing.loadEventEnd gets set when the fetch completes:

BOOMR.subscribe("xhr_send", (event) => {
    if (event.resource.type === "fetch") {
        event.resource.timing = new Proxy({}, {
            set: function(obj, prop, value) {
                if (prop === "loadEventEnd") {
                    console.log("FETCH completed");
                }
                obj[prop] = value;
                return true;
            }
        });
    }
})

It gets called twice though, you'll have to play with it.

iwindfree commented 1 year ago

@querymetrics Thanks for your help!