Code cleanliness in Jovo TypeScript

v3

#1

This sorta dances on the line between Jovo and the language, apologies if it’s considered off topic…

  1. In my code, as in the Jovo3 example I used as a starting point, a lot of the response code is replicated across intents. It would be cleaner to encapsulate that as a subroutine. But that parallel code references Jovo objects via ‘this’. I’m not sure how to write a subroutine that implicitly has the same ‘this’ as its caller. I could pass the object explicitly (poor man’s OO) but since it’s typescript I would need to declare the type of ‘that’ and I’m not sure what type the Jovo handler has. SO: What would be best practice here to factor out the shared logic?

  2. Related to that: Does the response code act when the call to tell/ask/etc. Is made, or do those just build a structure which is returned by the handler and then acted upon? I’ve been presuming the latter, but I’ve never been sure.


#2

You should be able to pass this and then accept jovo: Jovo in your subroutine.

import { Jovo } from 'jovo-framework';
// ...


subroutine(jovo: Jovo): void {
  // Example
  jovo.tell('...');
}

tell etc. don’t return the response right away, they write into the $output object. At the end of the Jovo handler, this output is then turned into a platform response and returned


#3

Many thanks!


#5

For what it’s worth, what I’ve come up with as a first draft is as follows. I’d still really like to see Jovo provide this kind of encapsulation, at least as an optional set of tools, so most apps wouldn’t need to be aware of platforms.

addUriUsage() here is a utility that appends a few URI parameters to identify where the request came from (mostly, fill in the “browser identification” field with the name of my skill so folks at the station can see it in their statistics.). I wouldn’t expect Jovo to deal with that detail, of course.

function setAudioResponse(that:Jovo,text:(string | string[] | SpeechBuilder), audioURI:string, audioOffset:number, audioDate:number, audioTitle:string) {
    if (that.isAlexaSkill()) {
	    that.$alexaSkill!.$audioPlayer! // guaranteed non-null by test
            .setOffsetInMilliseconds(audioOffset)
            .play(addUriUsage(audioURI), `${audioDate}`)
            .tell(text)
    } else if (that.isGoogleAction()) {
	  that.$googleAction! // guaranteed non-null by test
	    .$mediaResponse! // guaranteed non-null
	    .play(addUriUsage(audioURI), audioTitle);
	  that.$googleAction!.showSuggestionChips(['pause', 'start over']);
	  that.ask(text);
    }
    else {
	  console.error("Unexpected action type",objToString(that))
    }
}