Quantcast
Channel: Active questions tagged svelte - Stack Overflow
Viewing all articles
Browse latest Browse all 1541

Segment API call not completing execution when placed inside Svelte onMount lifecycle function

$
0
0

I am currently setting up Segment and ran into a problem that I can't explain. I am trying to execute an async segment method (analytics.identify) inside of my Svelte components onMount lifecycle function. The call to identify executes, but an HTTP request is never made to segment. Even if the call to .identify is awaited, the issue persists. If I move the call to analytics.identify outside of the onMount function, the HTTP request is made to segment without an issue. I encountered the same issue with RXJS subscriptions as well, but I cannot remember the details. All I remember is that I could not create an observable and subscribe to it in the onMount function at the same time.

Code that does not work:

// Executes but never resolves.onMount(async ()=>{        analytics.identify( user_id, {data: 'lorem ipsum'}})// Awaiting call never resolves.onMount(async ()=>{        await analytics.identify( user_id, {data: 'lorem ipsum'}})

Code that does work

// Dont call identify in onMount works.analytics.identify( user_id, {data: 'lorem ipsum'}onMount(async ()=>{})// Synchronous onMount works.onMount(()=>{    analytics.identify( user_id, {data: 'lorem ipsum'}        })

Another note: I know for a fact that analytics.identify is being called and executed, but is not resolving because if I add a method to the analytics object that calls identify like this:

analytics.identifyCustom = async function()=>{    console.log(`Called identify custom!`);     this.identify();}onMount(async ()=>{      analytics.identifyCustom();   })

The log is printed but no HTTP request is ever made to segment.

But this works:

analytics.identifyCustom = async function()=>{    console.log(`Called identify custom!`);     this.identify();}analytics.identifyCustom(); onMount(async ()=>{})

Just to be clear, I do not desire or need this code to execute in the onMount function, I would like to know why it does not work in the onMount function since this is the second time I have run into an issue with Svelte's onMount method and async code.

Source Code For Identify Function:

async identify(...args: IdentifyParams): Promise<DispatchedEvent> {    const [id, _traits, options, callback] = resolveUserArguments(this._user)(      ...args    )    this._user.identify(id, _traits)    const segmentEvent = this.eventFactory.identify(      this._user.id(),      this._user.traits(),      options,      this.integrations    )    return this._dispatch(segmentEvent, callback).then((ctx) => {      this.emit('identify',        ctx.event.userId,        ctx.event.traits,        ctx.event.options      )      return ctx    })  }private async _dispatch(    event: SegmentEvent,    callback?: Callback  ): Promise<DispatchedEvent> {    const ctx = new Context(event)    if (isOffline() && !this.options.retryQueue) {      return ctx    }    return dispatch(ctx, this.queue, this, {      callback,      debug: this._debug,      timeout: this.settings.timeout,    })  }export function dispatch(ctx, queue, emitter, options) {    return __awaiter(this, void 0, void 0, function () {        var startTime, dispatched;        return __generator(this, function (_a) {            switch (_a.label) {                case 0:                    emitter.emit('dispatch_start', ctx);                    startTime = Date.now();                    if (!queue.isEmpty()) return [3 /*break*/, 2];                    return [4 /*yield*/, queue.dispatchSingle(ctx)];                case 1:                    dispatched = _a.sent();                    return [3 /*break*/, 4];                case 2: return [4 /*yield*/, queue.dispatch(ctx)];                case 3:                    dispatched = _a.sent();                    _a.label = 4;                case 4:                    if (!(options === null || options === void 0 ? void 0 : options.callback)) return [3 /*break*/, 6];                    return [4 /*yield*/, invokeCallback(dispatched, options.callback, getDelay(startTime, options.timeout))];                case 5:                    dispatched = _a.sent();                    _a.label = 6;                case 6:                    if (options === null || options === void 0 ? void 0 : options.debug) {                        dispatched.flush();                    }                    return [2 /*return*/, dispatched];            }        });    });}

UPDATE:Figured out the issue, I think it has to do with the enclosing lexical context of the analytics object which I assume means calling a function in a different context than intended.The analytics object is loaded via script and saved into the window object like this window.analytics but I was then saving the window.analytics object into a variable and passing it around to different functions and calling it as is without window. This likely means the analytics object is highly dependent on its enclosing lexical context being the window object.

So this works:

onMount(async ()=>{       // Do not use the analytics objects passed to this component via getContext. Get the analytics object directly from window and call it using the window object.        window.analytics.identify( user_id, {data: 'lorem ipsum'}})

I would highly appreciate it if someone more knowledgeable about Javascript context could provide some insight on why this solution works so I know for the future.


Viewing all articles
Browse latest Browse all 1541

Trending Articles