Tag: JavaScript
Parallel API calls in JavaScript

Parallel API calls in JavaScript

Although JavaScript is single-threaded, it is relatively simple to avoid blocking the thread by writing code in an asynchronous style through the use of functions with an async keyword that returns a promise and only awaiting when you need it.

For example, the following code contains an API call in an async function.

1 private async CallAPI() {
2 const response = await axios.get('https://fooapi.com/Films')
3
4 console.log(response.data)
5 }

If we wanted to call two APIs then we could do the following.

1 private async CallAPI() {
2 const response = await axios.get('https://fooapi.com/Films')
3 const response2 = await axios.get('https://fooapi.com/Music')
4
5 console.log(response.data)
6 console.log(response2.data)
7 }
8

However because both API calls are being immediately awaited, this will result in the execution of the function stopping while it waits for the result of the first API call before making the second.

As we don't need that response to make the second API call, we can improve the performance of the code by moving the await keywords to the point we actually need the responses. Both API calls will now be made in parallel rather than the second waiting for the first to finish.

1private async CallAPI() {
2 const response = axios.get('https://fooapi.com/Films')
3 const response2 = axios.get('https://fooapi.com/Music')
4
5 console.log(await response.data)
6 console.log(await response2.data)
7}

Call an API for each item in an array in parallel

Those initial examples were quite easy to understand, but what if we have a scenario where you get a list of films showing at the cinema on a particular day and display the show times for each? You have two APIs at your disposal; The first returns all the films and the second returns the showtimes for a given film.

To get all the data you need you first need to call the API to get the films and then loop through them to call the second API and get the show times.

1interface Film {
2 id: string
3 name: string
4 showtimes: ShowTime[]
5}
6
7interface ShowTime {
8 date: Date
9}
10
11class FilmService {
12 public async GetShowtimes(): Promise<Film[]> {
13 const filmResponse = axios.get('https://fooapi.com/Films')
14
15 const films: Film[] = []
16 for (let e of (await filmResponse).data) {
17 console.log("Get Showtimes")
18 const showTimes = await axios.get(
19 `https://fooapi.com/Films/${e.id}/ShowTimes`
20 )
21 console.log("Got Showtimes")
22
23 films.push({
24 id: e.id,
25 name: e.name,
26 showtimes: showTimes.data,
27 })
28 }
29
30 return films
31 }
32}
33
34// Output
35// Get Showtimes
36// Got Showtimes
37// Get Showtimes
38// Got Showtimes
39// Get Showtimes
40// Got Showtimes

The problem with this code though is that its execution length will be the films API call response time + (showtime API response time * the number of films).

As each call to the second API have no dependencies on each other, it doesn't make any sense for them to have to be performed sequentially in the loop.

Instead, we can refactor for loop to be a map calling an async function which returns the new array and make use of Promise.all() to ensure they have all completed before returning the results.

1interface Film {
2 id: string
3 name: string
4}
5
6interface FilmWithShowtime extends Film {
7 showtimes: ShowTime[]
8}
9
10interface ShowTime {
11 date: Date
12}
13
14class FilmService {
15 public async GetShowtimes(): Promise<FilmWithShowtime[]> {
16 const filmResponse = await axios.get('https://fooapi.com/Films')
17
18 const films: FilmWithShowtime[] = await Promise.all(
19 filmResponse.data.map(async (e: Film) => {
20 return await this.getFilmWithShowtimes(e)
21 })
22 )
23
24 return films
25 }
26
27 private async getFilmWithShowtimes(film: Film): Promise<FilmWithShowtime> {
28 console.log("Get Showtimes")
29 const showTimes = await axios.get(
30 `https://fooapi.com/Films/${film.id}/ShowTimes`
31 )
32
33 console.log("Got Showtimes")
34
35 return {
36 id: film.id,
37 name: film.name,
38 showtimes: showTimes.data,
39 }
40 }
41}
42
43// Output
44// Get Showtimes
45// Get Showtimes
46// Get Showtimes
47// Got Showtimes
48// Got Showtimes
49// Got Showtimes
50

The API calls for show times will now app be made in parallel reducing the overall execution time of the code.

Making your code neater with TypeScript Paths

Making your code neater with TypeScript Paths

When I started doing development with TypeScript one of the first things that irked me was all those relative paths in import statements.

Code organisation and creating layers for maintainability is one of the things I'm most OCD about, so things like a service to call Prismics API end up in a folder called services. However, to then use it in a NextJs page a few folders deep ends up with an import statement such as this.

1import { prismicService } from '../../../src/services/Prismic/Prismic.service'

Yuck. Look at all those ../../ and to make things worse this also means if you move a file its no longer pointing in the right place.

Fortunately, there is a solution. Typescript supports path mapping through the tsconfig.json file.

First set a base URL property in the compiler options.

1{
2 "compilerOptions": {
3 "baseUrl": ".",
4 }
5}

At this point, you could get rid of all those ../ and just start at the src. e.g.

1import { prismicService } from 'src/services/Prismic/Prismic.service'

This is a lot better and we can now move files around, but it's still not perfect. The fact it's in a folder called src is a bit irrelevant for my liking.

Using the path's property we can define a grouping even lower down. e.g.

1// tsconfig.json
2{
3 "compilerOptions": {
4 "baseUrl": ".",
5 "paths": {
6 "@Services/*": ["src/services/*"]
7 }
8 }
9}
10
11// New import
12import { prismicService } from '@Services/Prismic/Prismic.service'

For more information on TypeScript paths check out the official documentation here.

Going a bit further

As well as just making your code a bit easier to read. This also makes a simple solution to swapping out code in a way that would otherwise need a dependency injection framework.

Coming from a .net background where dependency injection and interfaces are frequently used there can be a desire to do it with TypeScript too. Although it is possible (you can read my blog post on dependency injection with NextJs and Tsyringe here) it has quite a heavy overhead to the amount of code you need to write.

A simpler solution can be like what Vercel have done in NextJs commerce for the different providers.

Check out this part of their tsconfig file.

1 "paths": {
2 "@lib/*": ["lib/*"],
3 "@utils/*": ["utils/*"],
4 "@config/*": ["config/*"],
5 "@assets/*": ["assets/*"],
6 "@components/*": ["components/*"],
7 "@commerce": ["../packages/commerce/src"],
8 "@commerce/*": ["../packages/commerce/src/*"],
9 "@framework": ["../packages/local/src"],
10 "@framework/*": ["../packages/local/src/*"]
11 }

That @framework section at the end defaults to local, but gets swapped out to a commerce provider like bigcommerce or shopify. As each one implements the same methods, anything importing from @framework simply uses the correct code when the solution is built.

Which JavaScript for loop should I use?

Which JavaScript for loop should I use?

When given a choice of 4 seemingly different ways to do the same thing, I've always been the person that wants to know what the difference is? To often we can blindly write code the way the person before us did and not understand the reason to do it a certain way, but what if the scenario has changed. When multiple options exist there's usually a reason why. It can be a language style improvement to make things easier to write, but more often than not there's a fundamental difference in what it actually does.

So, for loops, four seems like a lot, gotta be some differences right?

for

This is likely to be the first type of for loop you encounter when learning to program. It's a very manual type of loop where you create a initial expression, a condition expression to keep running the loop and an increment expression.

1for (let i = 0; i < 5; i++) {
2 console.log(i);
3}
4
5// Result:
6// 0
7// 1
8// 2
9// 3
10// 4

The big downside of the for loop is it doesn't actually loop through a collection. e.g. If you had an array and wanted to loop through each of it's objects you could do this as follows:

1const arr = ['a', 'b', 'c'];
2
3for (let i = 0; i < arr.length; ++i) {
4 console.log(arr[i]);
5}

In effect the loop is incrementing a number and you then use that number to access the position of the array. The result is you have more code to write that isn't serving any real purpose.

However as this is a much more manual loop process you have far more control over the loop. e.g.

  • You could increment by a different number.
  • You could go backwards.
  • The condition might not be linked to the length of an array.
  • You might not even be looping through an array.

Pros

  • Potentially faster in performance.
  • Break statement can be used to come out of the loop.
  • It works with the await keyword.
  • Not just for looping through arrays.

Cons

  • Not as readable as others.
  • You have more code to write.

for...in

You probably don't want this one. Here's an example:

1const arr = ['a', 'b', 'c'];
2
3for (const i in arr) {
4 console.log(arr[i]);
5}
6
7// Result:
8// "a"
9// "b"
10// "c"

Although we're now specifically looping through a collection like an array and don't need to do all of that i < array.length stuff, what we're given isn't the object in the array but a property name to access it on the object.

Here's another example:

1const arr = ['a', 'b', 'c'];
2arr.foo = 'John'
3
4for (const i in arr) {
5 console.log(arr[i]);
6}
7
8// Result:
9// "a"
10// "b"
11// "c"
12// "John"

That looks a bit weird! The for...in loop doesn't just loop through an array, it loops through an objects enumerable properties, which could be the items in an array, but it could be other stuff too.

For this reason, unless your doing something quite niche its probably not the loop you are looking for and is likely to cause you an issue which your objects has one more property than you were expecting.

Pros

  • Can loop through all the enumerable properties on an object.

Cons

  • Looping through all the properties of an object isn't likely what you want.

forEach

As the name implies, a for each loop will iterate through each element in an array. Here's an example:

1const arr = ['a', 'b', 'c'];
2
3arr.forEach((i) => {
4 console.log(i);
5})
6
7// Result:
8// "a"
9// "b"
10// "c"

The forEach function takes an anonymous function as a parameter and will then call that function for each object in the array, passing in the object from the array.

This offers a big improvement over the initial for loop as we have a lot less code to write and we're actually given the object rather than a variable to go an find it.

However there are some downsides due to it effectively being a function call passing an anonymous function to execute.

Firstly you can't stop the forEach part way through. With the others you can use the break keyword to stop the iteration.

Secondly there's added confusion around the scope of what this is. Assuming your function is in a class, unless you use the arrow syntax (as in the example) you won't be able to access any of the other functions in your class as passing a regular function would change the scope.

1// This works
2class foo
3{
4 myFunction() {
5 const arr = ['a', 'b', 'c'];
6
7 arr.forEach((i) => {
8 this.outputValue(i)
9 })
10 }
11
12 outputValue(x) {
13 console.log(x);
14 }
15}
16
17// This Doesn't
18class foo
19{
20 myFunction() {
21 const arr = ['a', 'b', 'c'];
22
23 arr.forEach(function(i) {
24 this.outputValue(i)
25 })
26 }
27
28 outputValue(x) {
29 console.log(x);
30 }
31}

You also can't use an await within the foreach loop. e.g.

1async function run() {
2 const arr = ['a', 'b', 'c'];
3 arr.forEach(el => {
4 // SyntaxError
5 await new Promise(resolve => setTimeout(resolve, 1000));
6 console.log(el);
7 });
8}

Pros

  • Much shorter to write and easier to read.
  • Iterator provides the object from the array.

Cons

  • Easy to mess up context of this.
  • No way to break the loop.
  • Async/Await doesn't work on functions within the loop.
  • Can only loop through arrays.
  • It's performance is slower (nice article here comparing the performance differences), not to such an extent it would matter on a small object, but large objects could start to take a hit.

for...of

When looping through an array, the for...of loop combines the best of all the other loops. It has the same simple syntax of the for...in loop but instead of enumerating over enumerable properties, it loops through the iterable objects such as the items in an array.

Like the forEach loop you are provided with the object in the array rather than it's index or property name.

1const arr = ['a', 'b', 'c'];
2
3for (const i of arr) {
4 console.log(i);
5}
6
7// Result:
8// "a"
9// "b"
10// "c"

You can also break the loop and access properties outside of the loop.

1const stopValue = 'b'
2const arr = ['a', 'b', 'c'];
3
4for (const i of arr) {
5 console.log(i);
6 if (i == stopValue)
7 break;
8}
9
10// Result:
11// "a"
12// "b"

Pros

  • Lowest amount of extra code to write.
  • Iterator provides the object.
  • Doesn't use an anonymous function so scope doesn't change.
  • Loop can be stopped as needed.
  • Async still works.
  • Works with more than just arrays.

Cons

  • Have to be looping over the iterable items in an object.
  • Can't easily access the index value.

Conclusion

If you want to iterate through something like an array, for...of would be my recommendation to use. A for...in loop is likely to be less relevant but has its place, and for all other loops which don't relate to the objects in an array a good old for loop still has it's place.

Dependency Injection with NextJS and TypeScript

Dependency Injection with NextJS and TypeScript

Coming from a backend world, one thing that stands out when you start writing code in JavaScript, be it React, NextJS, Vue etc, is there's no great focus on code structure. Things like TypeScript bring back the concept of type checking that you'd be used to with a compiled language, and NextJS will give anyone familiar with ASP.NET MVC an alternative pattern for how a website should be constructed. But you can get the whole way through the NextJS tutorial without concepts like single responsibility, inversion of control or CQRS being mentioned once.

Now if your building a small site, maybe you can get away with not knowing or imlementing these things, but if you want to make code that's scalable or maintainable, it doesn't matter if you write in JavaScript or C# the same issues will exist but fortunately the same solutions do too.

Code Smells

Lets take a look at one of the functions on this site which gets the latest blog posts on the homepage.

1import gql from 'graphql-tag';
2import { Client, ApolClient } from '../prismicHelpers'
3
4// Models
5import { FeaturedPost } from "../../Models/FeaturedPost"
6
7const latestPostsQuery = gql`
8query latestPosts($category: String) {
9 allPosts (where : {category: $category}, first : 10, sortBy: post_date_DESC){
10 edges {
11 node {
12 category {
13 ... on Categories {
14 name
15 }
16 },
17 title,
18 image,
19 post_date
20 _meta {
21 uid
22 }
23 }
24 }
25 }
26}
27`;
28
29export const getLatestPosts = async (category?: String) : Promise<FeaturedPost[]> => {
30 const queryOptions = {
31 query: latestPostsQuery,
32 variables: { category },
33 };
34
35 return new Promise((resolve, reject) => { ApolClient.query(queryOptions).then(response => {
36 var posts: Array<FeaturedPost> = [];
37 response.data.allPosts.edges.map((edge: { node: { title: { text: any; }[]; category: any; image: any; post_date: Date; _meta: { uid: any; }; }; }, key: any) => {
38 posts.push({
39 type: "post",
40 title: edge.node.title[0].text,
41 image: edge.node.image,
42 uid: edge.node._meta.uid,
43 category: edge.node.category?.name,
44 postDate: edge.node.post_date
45 })
46 })
47 resolve( posts);
48 }).catch(error => {
49 reject(error);
50 });
51});
52};

This bit of code queries Prismic's GraphQL API to get the latest 10 articles for a category and then maps the result onto an internal FeaturedPost model.

Some good things about it:

  • The Prismic logic is abstracted away from the rest of the application by mapping the results to a model.
  • It follows single responsibility by doing just 1 job.
  • All config for the API (e.g. URI) are separated into a common function rather than being duplicated.

However even though I've seen countless JavaScript examples which don't even do these good things, if this were C# and I was reviewing a pull request, I'd say it smelt and needed changing.

Here's some bad things about it:

  • It's taking a dependency on Apollo Client, which while is a great client for doing GraphQL queries, at the rate JS frameworks come and go we can't say we'll never replace it and in a large application that has countless queries that would be a lot of code to update.
  • There's also no way anything can call this without also taking a dependency on it. That means I now have a hierarchy of at least 3 functions with each one dependent on the next. If I ever wanted to add unit tests to my project I'd have a big problem.

Dependency Injection using TSyringe

These issues can be solved using Dependency Injection. There's quite a few around but the one I've chosen is TSyringe (https://github.com/microsoft/tsyringe).

It's built by Microsoft, which gives me some confidence in the amount of QA that will have gone into it, but more importantly it works the way I expect a DI framework to work. There's a good chance this could be because I'm used to working in the Microsoft stack and it therefore has natural similarities to DI frameworks in their own languages.

How to add TSyringe to a NextJS project

There's nothing specifically NextJS about TSyringe, you could use it with any TypeScript/JavaScript project, it just happens that that's what my blog is built using. However it also had a few issues getting it to work and I couldn't any articles around which explained how.

To set it up...

First install the package tsyring and reflect-metadata using npm.

1npm install --save tsyringe reflect-metadata

Modify your tsconfig.json file to include the following settings, which will allow the use of decorators in TypeScript.

1{
2 "compilerOptions": {
3 "experimentalDecorators": true,
4 "emitDecoratorMetadata": true
5 }
6}

Now there's a few more packages your going to need. As of NextJS 12, Babel is no longer used and has been replaced with SWC to provide faster compile times. However TSyringe and most other DI frameworks use decorators to function (hence the tsconfig.js setting to turn them on), but the setting for SWC to allow this set to false in NextJS and there's no way for you to provide your own config. Fortunately Babel is still supported and you can customise it. Hopefully a future version of NextJS will address this.

Install the following packages as dependencies.

1npm install -D @babel/core @babel/plugin-proposal-class-properties @babel/plugin-proposal-decorators babel-plugin-transform-typescript-metadata

Add a .bablerc file to your project with the following settings.

1{
2 "presets": ["next/babel"],
3 "plugins": [
4 "babel-plugin-transform-typescript-metadata",
5 ["@babel/plugin-proposal-decorators", { "legacy": true }],
6 ["@babel/plugin-proposal-class-properties", { "loose": true }]
7 ]
8}

Finally add this import to your _app.tsx file.

1import "reflect-metadata";

Using TSyringe

We're now ready to convert the code I had before into something more maintainable.

First I'm going to create a GraphQL Client interface which all my queries will use when they want to call a graph API. This has one function called query, which my functions will pass the graph syntax too along with a variables object.

1import { DocumentNode } from "graphql";
2
3export interface graphClient {
4 query(query: DocumentNode, variables?: {}): any;
5}

With this interface I can now turn my getLatestPosts function into a class with a constructor that will take in the instance of graphClient.

1import { inject, injectable } from "tsyringe";
2import { iGetLatestPosts } from "./iGetLatestPosts";
3import gql from "graphql-tag";
4import { graphClient } from "../iGraphQl";
5
6// Models
7import { FeaturedPost } from "../../Models/FeaturedPost";
8
9@injectable()
10export class getLatestPosts implements iGetLatestPosts {
11 graphClient: graphClient;
12
13 constructor(@inject("graphClient") private graphClientParam: graphClient) {
14 this.graphClient = graphClientParam;
15 }
16
17 private latestPostsQuery = gql`
18 query latestPosts($category: String) {
19 allPosts(
20 where: { category: $category }
21 first: 10
22 sortBy: post_date_DESC
23 ) {
24 edges {
25 node {
26 category {
27 ... on Categories {
28 name
29 }
30 }
31 title
32 image
33 post_date
34 _meta {
35 uid
36 }
37 }
38 }
39 }
40 }
41 `;
42
43 public getLatestPosts = async (
44 category?: String
45 ): Promise<FeaturedPost[]> => {
46 return new Promise((resolve, reject) => {
47 this.graphClient
48 .query(this.latestPostsQuery, { category })
49 .then((response: any) => {
50 var posts: Array<FeaturedPost> = [];
51 response.data.allPosts.edges.map(
52 (
53 edge: {
54 node: {
55 title: { text: any }[];
56 category: any;
57 image: any;
58 post_date: Date;
59 _meta: { uid: any };
60 };
61 },
62 key: any
63 ) => {
64 posts.push({
65 type: "post",
66 title: edge.node.title[0].text,
67 image: edge.node.image,
68 uid: edge.node._meta.uid,
69 category: edge.node.category?.name,
70 postDate: edge.node.post_date,
71 });
72 }
73 );
74 resolve(posts);
75 })
76 .catch((error: any) => {
77 reject(error);
78 });
79 });
80 };
81}

Some things to note in this new class.

  • It's also now implementing an interface so that it can instantiated using DI.
  • The @injectable decorator allows TSyringe to inject the dependencies at runtime.
  • The constructor is decorating a parameter with @inject("graphClient") which means that parameter will be injected at runtime with whatever is configured against the graphClient token.
  • There are imports from tsyringe.
  • There are no references to the implementation of graphClient.
  • My function now has zero dependencies on Apollo Client and doesn't even know it's being used.

My implementation of graphClient looks like this.

1import { autoInjectable } from "tsyringe";
2import { DocumentNode } from "apollo-link";
3import ApolloClient from "apollo-client";
4import { NormalizedCacheObject } from "apollo-cache-inmemory";
5import { graphClient } from "./iGraphQl";
6
7@autoInjectable()
8export class apolloGraphClient implements graphClient {
9 apolloClient: ApolloClient<NormalizedCacheObject>;
10
11 constructor(apolloClient: ApolloClient<NormalizedCacheObject>) {
12 this.apolloClient = apolloClient;
13 }
14
15 public query = async (query: DocumentNode, variables?: {}): Promise<any> => {
16 const queryOptions = {
17 query: query,
18 variables: variables,
19 };
20
21 return new Promise((resolve, reject) => {
22 this.apolloClient
23 .query(queryOptions)
24 .then((response: any) => {
25 resolve(response);
26 })
27 .catch((error: any) => {
28 reject(error);
29 });
30 });
31 };
32}

Essentially all this function does is pass the parameters to the query function to an Apollo Client's query function. The Apollo Client itself is also being injected!

You may have expected this file to also instantiate the Apollo Client, and it could have, but I've gone to the extreme and the single purpose of this file is to act as a bridge between the business logic queries and what client is being used, so for that reason its injected.

You'll also notice that this time I'm decorating the class with @autoInjectable() and there is no decorator on the constructor parameter. More on this in a bit.

The homepage page for this site now looks like this.

1import Head from "next/head";
2
3import React, { useState } from "react";
4import { container } from "tsyringe";
5import { GetStaticProps } from "next";
6import Layout from "../layouts/layout";
7import { FeaturedRow1, FeaturedRow1Model } from "../components/featured-row-1";
8import SectionHeading from "../components/section-heading";
9import { iGetLatestPosts } from "../utils/queries/iGetLatestPosts";
10
11export default function Home({
12 latestPosts,
13 webDevelopmentPosts,
14 sitecorePosts,
15 devOpsPosts,
16}: {
17 latestPosts: FeaturedRow1Model;
18 webDevelopmentPosts: FeaturedRow1Model;
19 sitecorePosts: FeaturedRow1Model;
20 devOpsPosts: FeaturedRow1Model;
21}) {
22 return (
23 <Layout>
24 <Head>
25 <title>Hi My Name Is Tim</title>
26 </Head>
27 <SectionHeading heading="Latest Posts" link="blog"></SectionHeading>
28 <FeaturedRow1 posts={latestPosts}></FeaturedRow1>
29 <SectionHeading heading="Web Development" link="web-development"></SectionHeading>
30 <FeaturedRow1 posts={webDevelopmentPosts}></FeaturedRow1>
31 <SectionHeading heading="Sitecore" link="sitecore"></SectionHeading>
32 <FeaturedRow1 posts={sitecorePosts}></FeaturedRow1>
33 <SectionHeading heading="Devops" link="devops"></SectionHeading>
34 <FeaturedRow1 posts={devOpsPosts}></FeaturedRow1>
35 </Layout>
36 );
37}
38
39export const getStaticProps: GetStaticProps = async () => {
40 // Resolve interface for iGetLatestPosts
41 const instance = container.resolve<iGetLatestPosts>("iGetLatestPosts");
42
43 const latestPosts = await instance.getLatestPosts();
44 const webDevelopmentPosts = await instance.getLatestPosts("X8kFhxIAACcAn9oY");
45 const devOpsPosts = await instance.getLatestPosts("X8kFlRIAACkAn9pa");
46 const sitecorePosts = await instance.getLatestPosts("X8kFeBIAACkAn9nV");
47
48 return {
49 props: {
50 latestPosts: latestPosts,
51 devOpsPosts: devOpsPosts,
52 sitecorePosts: sitecorePosts,
53 webDevelopmentPosts: webDevelopmentPosts,
54 },
55 };
56};

Pages in NextJS TypeScript don't use classes, so we can't do constructor injection to get the instance of our getLatestPosts query class. Instead we are using container.resolve<iGetLatestPosts>("iGetLatestPosts") to get the instance to token name iGetLatestPosts from the DI container.

Lastly in the _app.tsx file I am registering the classes on the container. I'm only including the relevant bit of the file here.

1container.registerInstance(
2 ApolloClient,
3 new ApolloClient({
4 link: PrismicLink({
5 uri: prismicGraphUri,
6 repositoryName: prismicRepoName,
7 }),
8 cache: new InMemoryCache({ fragmentMatcher }),
9 })
10);
11
12container.register("graphClient", apolloGraphClient);
13container.register("iGetLatestPosts", getLatestPosts);

For the Apollo Client I am using register instance to register a specific instance and creating it at the same time. Notice the first parameter is the class name.

For the graph client and getLatestPosts query I am using the register method and rather than creating the instance of my implementation, just passing the class as the second parameter. The framework will handle creating an instance of them for me.

Notice the first parameter for the second two are strings rather than the actual interfaces. These are token names that the container will use to reference the instance value. With the Apollo Client, the framework will figure out the token name when it adds it to the container, but it can't do the same for an interface (if you try you will get an interface cannot be used as a type error) so you have to provide the token name instead. This is also the reason why the graph client implementation didn't need to use a string to inject the class instance in the constructor, whereas the other places did.

Personally I feel this is a weakness in the framework as it also means there is no type checking either when registering or resolving from the container.

Summary

We have seen that using JavaScript doesn't prevent us from using the same concepts as we would with any other more traditional backend language.

We've also seen how a NextJS application while slightly more awkward, can still be set up to use dependency injections.

Finally we've had a look at how to actually configure some code to have complete separation between logic within a solution.

Typescript: What to do when your third party NPM module doesn't have type declarations

Typescript: What to do when your third party NPM module doesn't have type declarations

As a developer who has probably spent slightly more time doing backend work than front end, and also who's front end work has been more about SPAs than making things look pretty, I really like what TypeScript brings to writing JavaScript. While it's often a nice break from C# to do write some code that doesn't require you to go and define every object there obviously a lot of benefits to do this (otherwise we would just make everything dynamic in C'#). Having file name's show up red in VS Code when there's a type error is a really nice feature.

However if you want to set your compiler options to strict, you will more than likely run into an issue with third part code coming from NPM. In the form of:

Type error: Could not find a declaration file for module MODULE NAME HERE

Here's a screen grab of the compiler error from my build server...

It's offering a nice line of hope by suggesting I run an npm command to add in the types. Sometime this works, but as not everyone feels the need to adopt TypeScript you'll find there's times when it doesn't.

The only solution to this is to write your own.

Type Definitions are stored in the node_modules folder, but as that isn't something you'll want to be adding to source control you'll need another folder. I call mine @types and have it in the root. Within that folder you then need a folder for each module requiring type definitions. The name of each folder should match the module name.

Here's mine:

To make the actual declaration file you'll need to name it index.d.ts and place it in the folder you just created. You can read more about how declaration files should be structured here, however there's an issue with writing a declaration file for a third party module.

1. It's very confusing to work out everything that should go in it

2. It's not your module so it might change

Unless your planning on helping develop the module and create the official type declarations, I suggest an easier option.

Create a file that looks like this:

1/// <reference types="node" />
2
3declare module 'module name here';

This is enough to satisfy the compiler. You won't get accurate types for the module, but they would only ever be as good as your interpretation anyway. This will at least unlock the ability for the rest of your application to continue functioning for strict type checking.

Redirecting to login page with AngularJs and .net WebAPI

Redirecting to login page with AngularJs and .net WebAPI

So here's the scenario, you have a web application which people log into and some of the pages (like a dashboard) contain ajax functionality. Inevitably the users session expires, they return to the window change a filter and nothing happens. In the background, your JavaScript is making http calls to the server which triggers an unauthorised response. The front end has no way to handle this and some errors appear in the JS console.

A few things are actually combining to make life hard for you here. Lets take a look at each in more detail.

WebAPI and the 301 Response

To protect your API's from public access a good solution is to use the Authorize attribute. i.e.

1public ActionResult GetDashboardData(int foo)
2{
3 // Your api logic here
4
5}

However chances are your solution also has a login page configured in your web.config so that your regular page controller automatically trigger a 301 response to the login page.

1 <authentication mode="Forms">
2 <forms timeout="30" loginUrl="/account/sign-in/" />
3 </authentication>

So now what happens, is instead or responding with a 401 Unauthorised response, what's actually returned is a 301 to the login page.

With an AJAX request from a browser you now hit a second issue. The browser is making an XMLHttpRequest. However if that request returns a 301, rather than returning it your JavaScript code to handle, it "helpfully" follows the redirect and returns that to your JavaScript. Which means rather than receiving a 301 redirect status back, your code is getting a 200 Ok.

So to summarise your API was set up to return a 401 Unauthorised, that got turned into a 301 Redirect, which was then followed and turned into a 200 Ok before it gets back to where it was requested from.

To fix this the easiest method is to create are own version of the AuthorizedAttribute which returns a 403 Forbidden for Ajax requests and the regular logic for anything else.

1using System;
2using System.Web.Mvc;
3
4namespace FooApp
5{
6 [AttributeUsage(AttributeTargets.Method)]
7 public class CustomAuthorizeAttribute : AuthorizeAttribute
8 {
9 protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
10 {
11 if (filterContext.HttpContext.Request.IsAjaxRequest())
12 {
13 filterContext.Result = new HttpStatusCodeResult(403, "Forbidden");
14 }
15 else
16 {
17 base.HandleUnauthorizedRequest(filterContext);
18 }
19 }
20 }
21}

Now for any Ajax requests a 403 is returned, for everything else the 301 to the login page is returned.

Redirect 403 Responses in AngularJs to the login page

As our Ajax request is being informed about the unauthorised response, it's up to our JavaScript code trigger the redirect in the browser to the login page. What would be really helpful would be to define the redirect logic in one place, rather than adding this logic to every api call in our code.

To do this we can use add an interceptor onto the http provider in angular js. The interceptor will inspect the response error coming back from the XmlHttpRequest and if it has a status of 401, use a window.locator to redirect the user to the login page.

1app.factory('httpForbiddenInterceptor', ['$q', 'loginUrl', function ($q, loginUrl) {
2 return {
3 'responseError': function (rejection) {
4 if (rejection.status == 403) {
5 window.location = loginUrl;
6 }
7 return $q.reject(rejection);
8 }
9 };
10}]);
11
12app.config(['$httpProvider', function ($httpProvider) {
13 $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
14 $httpProvider.interceptors.push('httpForbiddenInterceptor');
15}]);

You'll notice a line updating the headers. This is to make the IsAjaxRequest() method on the api recognise the request as being Ajax.

Finally you'll also notice the loginUrl being passed into the interceptor. As it's not a great idea to have strings like urls littered around your code, this is using a value recipe to store the url. The code to do this is follows:

1app.value('loginUrl', '/account/sign-in?returnurl=/dashboard/');
Two Google Maps Tips

Two Google Maps Tips

Centre a map on a collection of pins

The basic way to centre a Google Map is to give it co-ordinates of where you want the map to centre. But what if you have a collection of pin/markers and you want to show all of them but don't know beforehand where they will be.

The solution is to create a LatLngBounds object and for each of your pins call the extend method of your bounds object. Once this is done call fitBounds on your map.

1var bounds = new google.maps.LatLngBounds();
2
3$.each(mapMarkers(), function(index, value) {
4 bounds.extend(value.marker.position);
5});
6
7map.fitBounds(bounds);

Loading a map in a hidden div

The reason for doing this could be that you have a set of tabs and a non-visible one contains the Google Map. If you instantiate a Google Map when it isn't visible you end up with the smallest map size possible.

One popular solution for this is to only create the map when the tab is being displayed, which is a good option as it means the map is only loaded when it's viewed. However if your using something like Knockout to bind you've views to a model it may not be possible to attach an event to the tab change.

Google Maps actually have an event handler for just this scenario called resize. You simply need to trigger it at the point in which you can size the map.

1google.maps.event.trigger(map, 'resize')

HTML5 Series - Array

If your going to do any sort of JavaScript programming it's not going to be long until you have to work with an array, so there's a few array functions you need to know about.

Push and Pop
Push and Pop are functions that add and remove items from an array. The easiest way to understand what they are doing is to imagine your array as a stack of paper. When you push and item onto the array it's the same as putting it on the top of your pile. When you Pop an item off it's the same as taking the top item from the pile.

1var myArray = [] // Declare a new array
2myArray.push("Red");
3myArray.push("Blue");
4
5var value1 = myArray.pop();
6var value2 = myArray.pop();
7
8alert(value1); // should alert the value Blue
9alert(value2); // should alert the value Red

Foreach loop
Probably one of the most useful functions for an array is the for each loop. A for each loop is essentially calling a function for each item in the array (hence for each). This is particularly useful in all kinds of scenarios.

1var myArray = ["blue", "red", "green"];
2
3myArray.forEach(function (x) {
4 alert(x);
5});

Filter
As the name suggests filtering is a way to find items in your array. If you know C# then it works in a similar way to a lambda expression. The filter function takes a parameter of a function. Like the forEach loop the function is called on each item in the array, the function must then returns either true or false depending on if the filter criteria matched.

In this example notice that the result of myArray.filter is being assigned to another variable. This is because applying the filter wont actually remove items from the myArray array.

1var myArray = ["blue", "red", "green"];
2
3var results = myArray.filter(function(x) {
4 if (x == "blue")
5 return true;
6 else
7 return false;
8})
9
10results.forEach(function (x) {
11 alert(x);
12});

Some, Every
The some and every functions can be used to see if some items in the array match a criteria of if all of them do. They return either true or false.

Like the filter function, a function is passed as the criteria and returns either true or false.

1var myArray = ["blue", "red", "green"];
2
3alert(myArray.some(function (x) {
4 if (x == "blue")
5 return true;
6 else
7 return false;
8})); // Alerts true as 1 item in the array is blue
9
10alert(myArray.every(function (x) {
11 if (x == "blue")
12 return true;
13 else
14 return false;
15})); // Alerts false as not every item in the array is blue

Concat
Concat is used to combine 2 arrays into 2 new array.

1var myArray = ["blue", "red", "green"];
2var myArray2 = ["yellow", "orange"];
3
4var myArray3 = myArray.concat(myArray2);

Slice
Slice lets you create a new array from an existing by letting you specify the start and end item. Those items and the others between then form the new array.

1var myArray = ["blue", "red", "green"];
2var myArray2 = myArray.slice(2, 3); // selects red and green
3

Splice
Splice can be used to add and remove items in an array. The function has the syntax:

arrayName.splice(index, how many, items to add);

Note: the index value starts at 0.

For example in our colour array we could add yellow and orange in between red and green with the following:

1var myArray = ["blue", "red", "green"];
2myArray.splice(2, 0, "yellow", "orange");
3
4myArray.forEach(function (x) {
5 alert(x);
6});

Alternatively we could replace red and green with yellow and orange.

1var myArray = ["blue", "red", "green"];
2myArray.splice(1, 2, "yellow", "orange");
3
4myArray.forEach(function (x) {
5 alert(x);
6});

A couple of others

Sort - Sorts the array into alphabetical order

Reverse - Reverses the order of the array

HTML5 Series - Web Storage

One of the best benefits of HTML5 particularly for Web Apps is the ability to store data locally within the users browser. This means in many places you can speed your Web App up by fetching data once and then retrieving it locally in the future, rather than going back to a server each time.

There are 2 types of storage available localStorage and sessionStorage. The simple difference is that localStorage doesn't expire while sessionStorage expires at the end of the users session.

Both types store data in a key/value list and could not be simpler:

1// local storage
2localStorage.variableName = value;
3
4// session storage
5sessionStorage.variableName = value;

One thing to note though is you can only store text. If you want to store something more complex the simple solution is to convert it to and from JSON. E.g.

1var myColours = [ 'red', 'blue', 'green', 'yellow'];
2
3// Save to local storage
4localStorage.colours = JSON.stringify(myColours)
5
6// Retrieve from local storage
7var retrievedColorus = JSON.parse(localStorage.colours);

HTML5 Series - Error Handling

One thing you can say for certain about writing code is at some point your going to write something that error's. It may be picked up in code reviews, or by a tester, and then fixed but for certain as you are human at some point you will make a mistake. What's important though is what happens after the mistake.

If your a C# developer then good news JavaScript has the same try, catch, finally functionality that C# has and it works in the same way.

Wrap you code that could error with a try statement and curly braces and following it add in a catch statement with the code that you want to execute in the event of an error. Finally if you want some code to execute either way after both, place this in the finally block.

1try
2{
3 functionThatDoesntExists();
4}
5catch (err)
6{
7 alert(err.message);
8}
9finally
10{
11 //Code to execute at the end
12}

Notice the catch section is passed a parameter and I am then alerting a property of this called message. The error parameter can be useful for debugging what actually went wrong and contains a few other parameters.

  • Description
  • Message
  • Name
  • Number
  • Stack

Sometimes you may also want to cause an error to be thrown. You may be asking why, but consider people calling your functions may in-fact pass values that are not valid. You could detect this and throw an error containing some useful information before there incorrect parameter values causes your code to error and a less helpful message given.

1var err = new Error(1, "Oh dear, that's not going to work"); // First parameter is the error number, second is the message
2throw err;