Dealing with the Asynchronous Calls
Learn to deal with asynchronous calls. Additionally, deploy and test our application.
We'll cover the following...
Let’s take another look at the entrypoint of our pets folder. Here’s some relevant code:
export const getPet = async (event: APIGatewayProxyEventV2): Promise<Response> =>pipe(preparePetGet(event),TE.fromEither,TE.chain(retrieveFromDatabase),TE.map(JSON.stringify),TE.bimap(handleError, okResponse),TE.getOrElse(T.of))();export const postPet = async (event: APIGatewayProxyEventV2): Promise<Response> =>pipe(preparePetPost(event),TE.fromEither,TE.chain(putInDatabase),TE.bimap(handleError, createdResponse),TE.getOrElse(T.of))();
We discussed the prepare step, where we validate the event we received and transform it into a domain object.
TaskEither
for asynchronous calls
We also see some functions related to the database (retrieveFromDatabase
and putInDatabase
). As these are asynchronous calls, once again we’ll use a very useful monad transformer called TaskEither
. As we saw in earlier chapters, we can use fromEither
to lift our existing monad into a TaskEither
, making our subsequent work with our new favorite monad easier.
Going further downstream to our database files, we see it’s composition and piping all the way down, because all exported functions are composed of smaller functions:
const buildGet = (request: RetrievePetRequest) => ({TableName: process.env.DATABASE_NAME,Key: {ppId: `${PETS_ID_PREFIX}#${request.clientId}`,psId: request.id,},});const buildPost = (request: AddPetRequest) => ({TableName: process.env.DATABASE_NAME,Item: {ppId: `${PETS_ID_PREFIX}#${request.clientId}`,psId: request.id,id: request.id,clientId: request.clientId,name: request.name,age: request.age,cuteness: request.cuteness,type: request.type}});export const retrieveFromDatabase = (request: RetrievePetRequest) =>pipe(buildGet(request),(params) => TE.tryCatch(() => get(params), serverError),TE.chain(checkEmptyTE),TE.map(getItem));export const putInDatabase = (request: AddPetRequest) =>pipe(buildPost(request),(params) => TE.tryCatch(() => post(params), serverError),);
Use of parameters
The first step is building the right parameters for our call, for which we have some simple, pure functions. In the next step, we pass these params to the actual DynamoDB call inside the TaskEither
...