Code Monkey home page Code Monkey logo

Comments (9)

pooyaj avatar pooyaj commented on July 20, 2024 2

@tsheaff your solution looks great 🙌 I think we will build queuing mechanism for our npm package in near future as well so you don't have to wrap the library/import internal types

from analytics-next.

tsheaff avatar tsheaff commented on July 20, 2024 1

Ah OK great. I'll keep track of this issue until that's done. Can you leave this open and track that PR against this issue? I've renamed it for more clarity.

from analytics-next.

silesky avatar silesky commented on July 20, 2024 1

@tsheaff this is an awesome suggestion! We're actively working on this feature, I will tag you in the PR.

from analytics-next.

silesky avatar silesky commented on July 20, 2024 1

Feature merged in #436, should be available next release.

from analytics-next.

pooyaj avatar pooyaj commented on July 20, 2024

@tsheaff The npm version (unlike the CDN/snippet based solution) requires you to implement queuing yourself. Although the implementation should be straightforward. Can you check the response on this issue and see if that solves your issue: #374

from analytics-next.

tsheaff avatar tsheaff commented on July 20, 2024

Ah OK thanks for the fast reply @pooyaj!

That's unfortunate. I did see that queueing in the snippet. Unfortunately that doesn't work in Typescript. It seems like this could be built into the library. For example:

const [analytics] = AnalyticsBrowser.configure(...); // same options as `.load(...)`
await analytics.load();

Then analytics.track(...) etc can all work instantly, with the queueing behavior being something that moves inside the library and then is flushed when .load() finished. So loaded vs not is transparent to the caller.

Here's a solution that works for just 3 of the methods on analytics objects, but is fully typesafe. It does require importing from within the package tho. A sanity-check would be fantastic @pooyaj 🙏

import { Analytics, AnalyticsBrowser } from '@segment/analytics-next';
import { EventParams, PageParams, UserParams } from '@segment/analytics-next/dist/pkg/core/arguments-resolver';

type EnqueuedSegmentCall =
{
  type: 'track';
  args: EventParams;
} |
{
  type: 'page';
  args: PageParams;
} |
{
  type: 'identify';
  args: UserParams;
};

class Analytics {
  private analytics: Analytics | undefined;

  constructor() {
    this.load();
  }

  private async load() {
    const writeKey = process.env.REACT_APP_SEGMENT_WRITE_KEY;
    const cdnURL = process.env.REACT_APP_SEGMENT_CDN_PROXY;
    if (!writeKey) throw new Error('Segment Write Key Cannot Be Undefined');
    if (!cdnURL) throw new Error('Segment CDN URL Cannot Be Undefined');

    const [analytics] = await AnalyticsBrowser.load({ writeKey, cdnURL });
    this.analytics = analytics;

    this.flushQueue();
  }

  private enqueuedCalls: EnqueuedSegmentCall[] = [];

  private flushQueue() {
    this.enqueuedCalls.forEach((call) => {
      switch (call.type) {
        case 'track':
          return this.track(...call.args);
        case 'page':
          return this.page(...call.args);
        case 'identify':
          return this.identify(...call.args);
      }
    });
    this.enqueuedCalls = [];
  }

  track(...args: EventParams) {
    if (!this.analytics) {
      this.enqueuedCalls.push({ type: 'track', args: args });
      return;
    }
    this.analytics.track(...args);
  }

  page(...args: PageParams) {
    if (!this.analytics) {
      this.enqueuedCalls.push({ type: 'page', args: args });
      return;
    }
    this.analytics?.page(...args);
  }

  identify(...args: UserParams) {
    if (!this.analytics) {
      this.enqueuedCalls.push({ type: 'identify', args: args });
      return;
    }
    this.analytics?.identify(...args);
  }
}

export default new Analytics();

This then gives us this very clean interface throughout our calling code:

import analytics from '@analytics/analytics';

analytics.track(...);
analytics.page(...);
analytics.identify(...);

from analytics-next.

tsheaff avatar tsheaff commented on July 20, 2024

I think it will require a new interface as I mentioned as well so that you can get your analytics instance without any await

from analytics-next.

silesky avatar silesky commented on July 20, 2024

Released in https://github.com/segmentio/analytics-next/releases/tag/v1.38.0

from analytics-next.

dwilt avatar dwilt commented on July 20, 2024

Thank you so much for implementing this! You saved us a ton of work! It worked great!

from analytics-next.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.