Categories
Express JavaScript

Guide to the Express Response Object — Files and JSON

The Express response object lets us send a response to the client.

Various kinds of responses like strings, JSON, and files can be sent. Also, we can send various headers and status code to the client in addition to the body.

In this article, we’ll look at various properties of the response object, including files and JSON responses.

Methods

res.download

res.download sends a file response to the server.

For example, if we have:

const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => {  
  res.download('./public/foo.txt');  
})
app.listen(3000, () => console.log('server started'));

Then when a request is made to this route, then we’ll get a file downloaded.

We can save a file with a different than the file on the server by writing:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.download('./files/foo.txt', 'foobar.txt');  
});
app.listen(3000, () => console.log('server started'));

The file foo.txt from the server will be saved as foobar.txt by the client.

The download method also takes an error handler in case the download response fails.

For example, we can handle errors with the built-in error handler as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res, next) => {  
  res.download('./files/foo.txt', 'foobar.txt', err => next(err));  
});
app.listen(3000, () => console.log('server started'));

We called next with the error object passed in to pass it onto the error handler.

res.end([data] [, encoding])

res.end ends the response process. The method comes from response.end() of the http module.

We can use it to end the response without sending any data. To respond with data, we can use res.send() or other methods.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.status(404).end();  
});
app.listen(3000, () => console.log('server started'));

Then we sent a 404 response back to the client with no data.

res.format(object)

The res.format method takes the Accept HTTP header from the request object and use res.accepts to select a handler for the request.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.format({  
    'text/plain': () => {  
      res.send('hi');  
    }, 'text/html': () => {  
      res.send('<p>hi</p>');  
    }, 'application/json': () => {  
      res.json({ message: 'hi' });  
    }, 'default': () => {  
      res.status(406).end();  
    }  
  })  
});
app.listen(3000, () => console.log('server started'));

If we send a GET request to / with Accept header’s value set to text/plain , we get hi . If we send text/html as the Accept header’s value, we get <p>hi</p> , and so on.

default specifies the default response if none of the response types are matched.

It’ll work even if we abbreviate the MIME type names to something shorter:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.format({  
    text: () => {  
      res.send('hi');  
    }, html: () => {  
      res.send('<p>hi</p>');  
    }, json: () => {  
      res.json({ message: 'hi' });  
    }, default: () => {  
      res.status(406).end();  
    }  
  })  
});
app.listen(3000, () => console.log('server started'));

Then we get the same thing as before.

res.get(field)

The get method returns the HTTP response header specified by field . The match isn’t case sensitive.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {    
  res.send(res.get('Content-Type'));  
});
app.listen(3000, () => console.log('server started'));

res.json([body])

res.json lets us send a JSON response to the client. The parameter can be any JSON type, including object, array, string, Boolean, number, or null.

For example, if we have:

const express = require('express')  
const app = express()
app.use(express.json())  
app.use(express.urlencoded({ extended: true }))
app.get('/', (req, res) => {  
  res.json({ message: 'hi' });  
})
app.listen(3000, () => console.log('server started'));

Then we get:

{"message":"hi"}

as the response.

res.jsonp([body])

We can use this to send a JSON response with JSONP support. It returns a callback with the JSON body passed in.

For example, we can use it as follows:

const express = require('express');  
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());  
app.use(bodyParser.urlencoded({ extended: true }));
app.get('/', (req, res) => {  
  res.jsonp({ user: 'foo' });  
});
app.listen(3000, () => console.log('server started'));

If we send a GET request with ?callback=cb as the query string, then we get:

// typeof cb === 'function' && cb({"user":"foo"});

as the response. If we leave out the callback search parameter, then we get a normal JSON response:

{  
    "user": "foo"  
}

Conclusion

We can send various kinds of responses easily with the response object.

To send files, we can use download .

To send different things according to the Accept request header, we can use the format method.

Finally, to send JSON, we can use the json or jsonp methods depending on if we need to call a callback function on the client or not.

Categories
Flow JavaScript

JavaScript Type Checking with Flow — Intersection Types

Flow is a type checker made by Facebook for checking JavaScript data types. It has many built-in data types we can use to annotate the types of variables and function parameters.

In this piece, we’ll look at how to use intersection types to create variables that accept a combination of multiple types.


Defining Intersection Types

We can create intersection types by separating multiple types with an & sign as follows:

Type1 & Type2 & ... & TypeN

We can also break the expression above into multiple lines with the leading & sign:

type Bar =  
  & Type1  
  & Type2  
  & ...  
  & TypeN

Also, we can create intersection types from other intersection types:

type A = Type1 & Type2;  
type B = Type3 & Type4;  
  
type Foo = A & B;

Properties of Intersection Types

When we call a function that accepts an intersection type, we must pass in data that has all of those types. But inside the function, we can treat them as being one of the types in the intersection type.

For example, if we define the following function:

type A = { a: number };  
type B = { b: boolean };  
type C = { c: string };  
  
function foo(value: A & B & C) {  
    
}

Then we can treat value as having to be any one of A , B and C, as follows:

function foo(value: A & B & C) {  
  let a: A = value;  
  let b: B = value;  
  let c: C = value;    
}

Impossible Intersection Types

We can create intersection types that are impossible. For example, we can create a type that’s an intersection of string and boolean, as follows:

type StringBoolean = string & boolean;

This type is useless since no value can be both a string and a boolean, so we can’t assign anything to it.


Intersections of Object Types

An intersection of object types means that an object of the intersection type must have all the properties of both types.

For example, suppose we have the following intersection type:

type Foo = { foo: string };  
type Bar = { bar: boolean };
type FooBar = Foo & Bar;

The variable that we create of type FooBar must have all the properties of both Foo and Bar:

let foobar : FooBar = {  
  foo: 'abc',  
  bar: true  
};

When two object types have the same property name but a different type, then when they’re intersected together, the new property with the same name will have the intersection of both types as the new type.

For example, suppose we have:

type Foo = { foo: string };  
type Bar = { foo: boolean };
type FooBar = Foo & Bar;

Then foo will have the string & boolean intersection type, which means that no value can be set to it.

With intersection types, we can create types that have all the properties of each type that form the intersection type. We can also create intersection types from primitive types, but they’re useless since nothing can be assigned to variables of those types.

This means that intersection types are useful for object types mostly.

Categories
Flow JavaScript

JavaScript Type Checking with Flow — More Data Types

Flow is a type checker made by Facebook for enforcing data types in JavaScript. It has many built-in data types we can use to annotate the types of variables and function parameters.

In this article, we’ll look at some data types unique to Flow, including maybe types, literal types, mixed and any types

Maybe Types

Maybe types are for annotating variables or parameters that are optional. It’s indicated by a question mark in front of the type name.

For example, ?string and ?number are maybe types for string and number respectively.

With ?string type, we can set it with a string, null, undefined, or nothing. For example, we can write:

let a: ?string = null;  
let b: ?string = undefined;  
let c: ?string;  
let d: ?string = 'abc';

The rules are the same for parameters:

maybeString(null);  
maybeString(undefined);  
maybeString();  
maybeString('abc');

Anything else, like:

maybeString(0);

will get us errors.

Optional Object Properties

We can mark an object property as optional by adding a ? after the property name.

For example, we can write:

let x: { foo?: string } = {};  
let y: { foo?: string } = { foo: 'abc' };

This rule also applied to parameters, so the following code will work:

function optionalFoo(val:  { foo?: string }){}
optionalFoo({});  
optionalFoo({ foo: 'abc'});

undefined also works. For example, we can write:

let y: { foo?: string } = { foo: undefined };

We can also write:

function optionalFoo(val:  { foo?: string }){}  
optionalFoo({ foo: undefined });

Any other values for the foo property will result in an error.

Default Function Parameter Values

Like JavaScript since ES2015 or later, we can assign default values to function parameters. For example, we can write:

function foo(value: string = "foo") {}

The default value for the value parameter is 'foo' .

We can then pass in a string, undefined or nothing to the foo function. For example, the following will work:

foo("bar");       
foo(undefined);
foo();

Passing in undefined or nothing will result in 'foo' being the value for the value parameter.

Everything else passed in will result in an error. For example, the following won’t work:

foo(null);

Literal Types

Flow has literal types to let us create variables or function parameters that can only be assigned a few possible values.

For example, we can write:

let x: 1|2 = 1;

Since x has the type 1|2 which means that x can only be assigned the value 1 or 2. Each possible value is separated by the | symbol. The | symbol is the union type operator. It indicates the type is either of the types indicated in the operands.

If we write:

let y: 1|2 = 3;

We get an error since x has been assigned a value that’s not in the list of possible values for y .

This is the same for function parameters. For example, the following will work:

function fruitFn(fruit: 'orange' | 'apple'){}fruitFn('apple');

While the following code will fail to compile:

function fruitFn(fruit: 'orange' | 'apple'){}fruitFn('banana');

Mixed Type

The mixed type lets us assign any value to a variable or a function parameter. For example, we can write:

function foo(value: mixed) {  
    
}
foo('apple');  
foo(1);  
foo(true);

With mixed types, we have to figure out the actual type before doing manipulating the parameter or variable. We can use the typeof or instanceof operator for checking the type before operating on them.

For example, we can check if a value is a string or number as follows:

function foo(value: mixed) {  
  if (typeof value === 'number'){  
    return value;  
  }  
  else if (typeof value === 'string'){  
    return +value;  
  }  
}

We can also use the instanceof operator to check the constructor the object is created from and run code accordingly:

function foo(value: mixed) {  
  if (value instanceof Date){  
    return value.toUTCString();  
  }  
  else if (value instanceof Object){  
    return value.toString();  
  }  
}

If Flow doesn’t know what type of object we’re passing in, then it won’t accept the code. For example, we can’t write:

function foo(value: mixed) {  
  return value.toString();  
}

We’ll get the error:

[Flow] Cannot call `value.toString` because property `toString` is missing in mixed [1].

Any Type

The any type let us opt out of type checking with Flow. It lets us assign it to anything if it’s a variable and pass in anything if it’s a function parameter.

It doesn’t check if the method we’re calling actually exists or the operator we’re using actually works with the data we’re passing in.

any type isn’t the same as the mixed type. mixed type is checked for the type. We’ve to check the type with our code because we can do anything with the variable or parameter with the mixed type.

Variables or parameters with the any type do not have any type check, so Flow lets us do anything we want with variables of any type. This means that we can get run-time errors like any other JavaScript code if we didn’t check the type of data is being manipulated.

When variables or parameters of type any are assigned to other variables without type annotation. It’ll be set as the any type.

We should stop this by annotating our variables or parameters with a type.

For example, we should write:

function fn(obj: any) {  
  let bar: number = obj.bar;  
}

Then type checking will be done on bar . This means that

function fn(obj: any) {  
  let bar: number = obj.bar + 1;    
}

will work, but

function fn(obj: any) {  
  let bar: number = obj.bar + 'abc';    
}

will fail.

Flow has many data types that make type annotation convenient coming from JavaScript. We can use the mixed type to pass in anything or assign a variable to anything, but then we can check the type in our code after passing in the value or variable assignment.

any type bypasses Flow’s type checking and lets us assign any value or pass any value to a function.

Literal types lets us set a variable or parameter to the possible values listed, separated by a | symbol.

Maybe types make properties or variables be optionally passed in or stay undefined .

Categories
JavaScript Rxjs

More Rxjs Transformation Operators — mergeScan and Pluck

Rxjs is a library for doing reactive programming. Creation operators are useful for generating data from various data sources to be subscribed to by Observers.

In this article, we’ll look at some transformation operators like mergeScan , pairwise , partition , and pluck operators.

mergeScan

The mergeScan operator applies an accumulator function over the source Observable where the accumulator function itself returns an Observable, where each intermediate Observable returned is merged into the output Observable.

It takes up to 3 arguments. The first is an accumulator function that’s called on each source value.

The second argument is the seed parameter, which takes the initial accumulation value.

The last argument is an optional argument which takes the maximum number of concurrent input Observables to be subscribed to concurrently.

For example, we can use it as follows:

import { of, interval } from "rxjs";  
import { mapTo, mergeScan } from "rxjs/operators";
const interval$ = interval(5000);  
const one$ = interval$.pipe(mapTo(1));  
const seed = 0;  
const count$ = one$.pipe(mergeScan((acc, one) => of(acc + one), seed));  
count$.subscribe(x => console.log(x));

The code above has the interval$ Observable which is mapped to the value 1 with the mapTo operator. Then we set the seed initial value to 0.

Then we send the emitted values of the interval$ Observable to the accumulator function via the mergeScan operator, which keeps adding 1 as the values from interval$ is emitted. Then we get the emitted number from $count when we subscribe to count$ .

pairwise

pairwise groups pairs of consecutive emissions from the source Observable together then emit them as an array 2 values.

It takes on arguments.

For example, we can use it as in the following example:

import { of } from "rxjs";  
import { pairwise } from "rxjs/operators";
const of$ = of(1, 2, 3, 4, 5, 6);  
const pair$ = of$.pipe(pairwise());  
pair$.subscribe(x => console.log(x));

The code above will group the emitted values from the of$ Observable into pairs with the pairwise() operator then emitted the values. Then we get the following output from the console.log :

[1, 2]  
[2, 3]  
[3, 4]  
[4, 5]  
[5, 6]

partition

The partition operator splits the source Observable into 2, where one has the values that satisfy a predicate and the other with values that doesn’t.

It takes up to 2 arguments. The first is the predicate , which is a function that evaluates each value emitted by the source Observable. Then if the function returns true , then the value emitted on the first return Observable in the emitted array. Otherwise, it’s emitted in the second Observable with that emitted array.

The second is the thisArg , which lets us set the value of this inside the predicate function.

For instance, we can use it as follows:

import { of } from "rxjs";  
import { partition } from "rxjs/operators";
const of$ = of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);  
const parts = of$.pipe(partition(x => x % 2 === 0));  
const [even, odd] = parts;  
odd.subscribe(x => console.log(`odd numbers: ${x}`));  
even.subscribe(x => console.log(`even numbers: ${x}`));

In the code above, we have the of$ Observable with some numbers. Then we pipe it into the partition operator, which takes a predicate function that checks whether a number emitted from the of$ Observable is even.

parts will be set to the 2 Observables returned from the partition operator. The even Observable has the even numbers emitted, and the odd Observable has odd numbers emitted.

Then we get the following output from the odd Observable:

odd numbers: 1  
odd numbers: 3  
odd numbers: 5  
odd numbers: 7  
odd numbers: 9

Then we get the following output from the even Observable:

even numbers: 2  
even numbers: 4  
even numbers: 6  
even numbers: 8  
even numbers: 10

pluck

The pluck operator map each emitted value from the source Observable to its specified nested property.

It takes one argument which is the properties object, which are the nested properties to pluck from each source value.

For example, we can use it as follows:

import { of } from "rxjs";  
import { pluck } from "rxjs/operators";
const people = [  
  { name: { firstName: "Mary" }, age: 10, gender: "female" },  
  { name: { firstName: "Joe" }, age: 11, gender: "male" },  
  { name: { firstName: "Amy" }, age: 10, gender: "female" }  
];  
const people$ = of(...people);  
const plucked = people$.pipe(pluck("name", "firstName"));  
plucked.subscribe(x => console.log(x));

The code above, has a people array where each entry has a name object. We emit the values with the of operator and then pipe the emitted values and use pluck to get the nested property firstName , which is inside name .

Then we should get:

Mary  
Joe  
Amy

as the output on the last line.

mergeScan applies an accumulator function over the source Observable where the accumulator function itself returns an Observable. Then each intermediate Observable returned is merged into the output Observable and emitted together.

pairwise groups pairs of consecutive emissions from the source Observable together then emit them as an array 2 values.

The partition operator splits the source Observable into 2, where one has the values that satisfy the condition returned in the predicate function and the other with values that doesn’t.

The pluck operator map each emitted value from the source Observable the value of the specified nested property.

Categories
JavaScript Vue

List Rendering with Vue.js — Numbers, Components, and Templates

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at rendering a range of numbers, rendering components and templates, and more.

v-for with a Range

v-for can take an integer to render a range of numbers. For example, if we have the following:

src/index.js :

new Vue({  
  el: "#app",  
  data: {}  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="[https://cdn.jsdelivr.net/npm/vue/dist/vue.js](https://cdn.jsdelivr.net/npm/vue/dist/vue.js)"></script>  
  </head><body>  
    <div id="app">  
      <span v-for="num in 10">  
        {{num}}  
      </span>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then we see:

1 2 3 4 5 6 7 8 9 10

v-for on a Template

We can use v-for to loop through template elements. For example, we can write:

src/index.js :

new Vue({  
  el: "#app",  
  data: {}  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="[https://cdn.jsdelivr.net/npm/vue/dist/vue.js](https://cdn.jsdelivr.net/npm/vue/dist/vue.js)"></script>  
  </head> <body>  
    <div id="app">  
      <template v-for="num in 10">  
        <span>  
          {{num}}  
        </span>  
        <span>|</span>  
      </template>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then we get:

1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |

displayed on the screen.

v-for with v-if

v-for has higher priority than v-if if they’re used together.

However, we shouldn’t use them together because of the higher precedence of v-for over v-if .

If we want to filter some elements out when we render items from an array, we should use a computed property.

If we only render a small fraction of array elements, it has to iterate over the entire list and then check if the expression we set it truthy.

For example, the following JavaScript and HTML code:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    numbers: [1, 2, 3, 4, 5]  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <span v-for="num in numbers" v-if="num !== 3">  
        {{num}}  
      </span>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

is not very efficient since every time the loop is rendered, Vue has to iterate through every element and then check if num !== 3 is true .

Instead, we should use a computed property as follows:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    numbers: [1, 2, 3, 4, 5]  
  },  
  computed: {  
    not3() {  
      return this.numbers.filter(p => p !== 3);  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <span v-for="num in not3">  
        {{num}}  
      </span>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

The code above is more efficient because not3 is only recomputed when numbers change.

Also, only the items in not3 is iterated through during render, so v-for doesn’t have to loop through all the items.

There’s also less logic in the template, which keeps it clean. Maintenance is much easier.

We can also get performance benefits from moving v-if to the parent element that has the v-for , so whatever’s inside is only rendered when the condition is met.

For example, if we have:

src/index.js :

new Vue({  
  el: "#app",  
  data: {  
    persons: ["Joe", "Jane", "Mary"],  
    show: false  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>    <body>  
    <div id="app">  
      <div v-if="show">  
        <div v-for="person in persons">  
          {{person}}  
        </div>  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then nothing is rendered since show is false . Vue doesn’t have to do the work to look at whatever’s inside.

This is much better than:

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>    <body>  
    <div id="app">  
      <div v-for="person in persons" v-if="show">  
        {{person}}  
      </div>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, Vue has to loop through each entry and check if the condition in the v-if returns a truthy value.

As we can see, even though the code is only slightly different, but the performance implications are big.

v-for with a Component

We can use v-for on custom components just like with any other element.

For example, we can write the following:

src/index.js :

Vue.component("num", {  
  props: ["num"],  
  template: "<span>{{num}}</span>"  
});new Vue({  
  el: "#app",  
  data: {  
    numbers: [1, 2, 3, 4, 5]  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head> <body>  
    <div id="app">  
      <num v-for="num in numbers" :num="num" :key="num" />  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then we get:

12345

displayed on the screen.

Note that we have the :key attribute provided. This is required since Vue 2.2.0.

Also, we passed num into the num component’s num prop by writing:

:num="num"

This lets us inject what we want to the component, reducing coupling between them.

Conclusion

We can render a range of numbers with v-for by providing it with a number instead of an array or an object.

v-for and v-if shoudn’t be used together so that v-if doesn’t have to run in each iteration and we can also reduce the number of items that are iterated through.

Also, we can loop through template and components with v-for like any other element.