Categories
Programming

My Adventure With JavaScript Promises and Fetch API

I’m too rookie to offer a full-blown tutorial on JavaScript Promises and the Fetch API. However, some of the insights and concepts I learned could be helpful to you if you’re stepping into JavaScript Promises and the Fetch API for the first time.

What are “Promises?”

Mozilla’s MDN has a simple definition of Promises. “The Promise object represents an asynchronous operation’s eventual completion (or failure) and its resulting value.” You can think of it as a chain of codes that runs after parts of other codes are complete.

What are these chains? They’re then() methods that take function handles as parameters. Below is an example provided by Mozilla:

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("foo");
  }, 300);
});

myPromise
  .then(handleFulfilledA, handleRejectedA)
  .then(handleFulfilledB, handleRejectedB)
  .then(handleFulfilledC, handleRejectedC);

Promises are useful. They auto-detect successes and failures, giving you an easy way to call successive functions without defining additional event handlers and other cumbersome tasks. That’s my opinion, at least. I’m still a rookie JavaScript user.

But I mainly dealt with Promises because I needed to utilize JavaScript’s Fetch API. My goal was to connect with OpenAI’s API for some cool machine-learning stuff. It’s not important why I needed to use OpenAI; instead, I’ll discuss how I leveraged Fetch API, and some learnings gained about Promises.

What is the Fetch API?

The Fetch API is a replacement for jQuery’s AJAX function. AJAX allows you to send a GET or POST request to another URL and consume the response. It’s useful in my opinion, but I’m about moving into the future; jQuery represents the past. Plus, I prefer dealing with vanilla JS over any libraries.

Fetch API leverages Promises. It’s instantiated by calling the fetch() function. You can append additional parameters depending on the type of request you’re making. The fetch() can be stored as an anonymous function variable and called anytime.

How do I use the Fetch API to connect with OpenAI? Let’s explain how my MVP tool works. I setup an OpenAI prompt (which is in the background and will be sent with my request to their API). A person enters content into a form (the right side) sent to OpenAI (note: this request doesn’t directly go to OpenAI; instead, I created a PHP script that connects to OpenAI using the content form and temperature text field as parameters). The API response is displayed within another form (the left side). This action happens when clicking on the “Preview” button.

OpenAI form input

How is all this coded? The first step is the grab the content of the input form. Here’s the code below (I created a function called preview_keywords_formdata):

function preview_keywords_formdata() {
	var content_form = new FormData();

	content_form.append( "openai_content", document.getElementById("openai_content").value );
	content_form.append( "temperature", document.getElementById("temperature").value );

	return content_form;
}

The code above creates a FormData object which contains form inputs from the content form (“openai_course_content”) and the temperature text field (“temperature”) (see the image further above).

I created another function that will run when the “Preview” button is pressed. Its name doesn’t matter, but I attach it to the HTML of the “Preview” button tag using an onclick attribute. The first line of the function is a call to preview_keywords_formdata() to get FormData object (which has the content and temperature setting I want to send to OpenAI API).

var formdata = preview_keywords_formdata();

Now I will setup Fetch API. I will specify the URL of the PHP script that connects to OpenAI, specify a POST request, and append the FormData stored in the “formdata” variable.

const openai_request = "openai.php";
const openai_init = {
  method: "POST",
  body: formdata
};

I’m ready to call the Fetch API, using the variable “openai_request” as the URL and “openai_init” as the function settings. The PHP script returns a JSON string (“response”), which is turned into a JavaScript object with “response.json()”; since Promise chains are like an anonymous function, we have to return data, so I use “return data”. The data is stored in the variable “open_ai”.

const open_ai = fetch( openai_request, openai_init )
.then( (response) => response.json() )
.then( (data) => { return data } );

At this point, no action has happened. If I try to debug “open_ai” [with console.log], I won’t retrieve any useful data from it. I’ll only see “Promise object”. I have to process the variable, and I do that by creating an anonymous function that runs asynchronously.

const get_openai = async () => {
};

Within the anonymous function get_openai(), I need to call the variable “open_ai”, but I need to ensure that nothing happens until the fetch() function finishes. Hence, why I use await keyword in front of “open_ai”. I store the resulting data grab, represented as a JSON object, within the variable “openai_data”.

const openai_data = await open_ai;

Now, I have defined how the OpenAI response data is processed. Still, no action has happened. How do I start the sequence of processing the response data? I simply called the anonymous function I defined.

const get_openai = async () => {
	const openai_data = await open_ai;
};
	
get_openai();

There’s more that I do with “openai_data” than what’s shown here. Since it’s a JSON object, I do error-handling checks by using the in operator to check for the presence of specific object properties.

The Entire Code Example

Here’s the complete code example:

function preview_keywords_formdata() {
	var content_form = new FormData();

	content_form.append( "openai_content", document.getElementById("openai_content").value );
	content_form.append( "temperature", document.getElementById("temperature").value );

	return content_form;
}

function send_to_openai() {
	var formdata = preview_keywords_formdata();

	const openai_request = "openai.php";
	const openai_init = {
	  method: "POST",
	  body: formdata
	};

	const open_ai = fetch( openai_request, openai_init )
	.then( (response) => response.json() )
	.then( (data) => { return data } );

	const get_openai = async () => {
		const openai_data = await open_ai;

	}

	get_openai();
}

...
/// The HTML Tag Which Triggers the Fetch API ///
<button onclick="send_to_openai();">Preview</button>