Deno Runtime

Learn about the available functions in Deno and how to work with APIs in it.

Functions

Deno provides a set of functions included in the runtime as globals in the Deno namespace. The runtime APIs can be used to do the most elementary, low-level things.

Types of functions

Two types of functions are available on Deno without any imports:

  • Web APIs
  • The Deno namespace

Whenever there’s a behavior in Deno that also exists on the browser, Deno mimics the browser APIs. Those are Web APIs. If you’re coming from the JavaScript world, you’ll probably be familiar with most of them. We’re speaking about functions such as fetch, addEventListener, and setTimeout, and objects such as window, Event, and console, among others.

Code written using Web APIs can be bundled and run in the browser without transformations.

The other big part of the APIs exposed by the runtime lives inside a global namespace named Deno. We can use the REPL and the documentation, two of the things we explored earlier in this course, to explore it and get a quick grasp of what functions it includes.

Note: To access the documentation of all the symbols included in Deno, run the doc command with the --builtin flag: deno doc --builtin.

Terminal 1
Terminal
Loading...

Stability

The functions inside the Deno namespace are considered stable from version 1.0.0 onward. This means the Deno team will try to support them across newer versions and will do its best to keep them compatible with future changes.

Features still not considered stable for production live under the --unstable flag, as we’ve used them in previous examples.

The documentation of unstable modules can be accessed using the --unstable flag with the doc command or by accessing this page of Deno’s documentation. The standard library is not yet considered stable by the Deno team, so they have a different version from the CLI (currently, we are using version 0.83.0).

In contrast with the Deno namespace functions, the standard library doesn’t normally need the --unstable flag to run. The exception is if any module from the standard library uses unstable functions from the Deno namespace.

Program lifecycle

Deno supports the browser compatible load and unload events that can be used to run setup and cleanup code.

Handlers can be written in two different ways:

  • With addEventListener
  • By overriding the window.onload and window.onunload functions.

The load events can be asynchronous, but the same is not true for unload events because they can’t be canceled.

Using addEventListener enables us to register unlimited handles, for instance, create a file called add-event-listener:

Press + to interact
addEventListener("load", () => {
console.log("loaded 1");
});
addEventListener("unload", () => {
console.log("unloaded 1");
});
addEventListener("load", () => {
console.log("loaded 2");
});
addEventListener("unload", () => {
console.log("unloaded 2");
});
console.log("Exiting...");

If we run the preceding code, we get the following output:

deno run program-lifecycle/add-event-listener.js
Press + to interact
Exiting...
loaded 1
loaded 2
unloaded 1
unloaded 2

Another way to schedule code to run on setup and teardown phases is by overriding the onload and onunload functions from the window object. These functions have the particularity that only the last to be assigned runs. This happens because they override one another; see the following code, for instance:

Press + to interact
window.onload = () => {
console.log("onload 1");
};
window.onunload = () => {
console.log("onunload 1");
};
window.onload = () => {
console.log("onload 2");
};
window.onunload = () => {
console.log("onunload 2");
};
console.log("Exiting");

By running the preceding program, we got the following output:

deno run program-lifecycle/window-on-load.js
Press + to interact
Exiting
onload 2
onunload 2

If we then look at the initial code we wrote, we can understand that the first two declarations were overridden by the two declarations following them. That’s what happens when we override the onunload and onload functions.

window.onload = () => {
  console.log("onload 1");
};
window.onunload = () => {
  console.log("onunload 1");
};
window.onload = () => {
  console.log("onload 2");
};
window.onunload = () => {
  console.log("onunload 2");
};
console.log("Exiting");
Program lifecycle

Web APIs

To demonstrate that we can use the Web APIs the same way we can use on the browser, we’ll write a rudimentary program that fetches the Deno website logo, converts it to base64, and prints to the console an HTML page with the base64 of the image there. Let’s do this by following these steps:

  1. Create a file called fetch-Deno-logo.js, and fetch the request to "https://deno.land/logo.svg":

fetch("https://deno.land/logo.svg")

2. Convert it into blob:

fetch("https://deno.land/logo.svg").then(r =>r.blob())
  1. Get the text out of the blob object, and convert it into base64 using btoa :

Press + to interact
fetch("https://deno.land/logo.svg ")
.then(r =>r.blob())
.then(async (img) => {
const base64 = btoa(
await img.text()
)
});
  1. Print to the console an HTML page with an image tag using the base64 image:

Press + to interact
fetch("https://deno.land/logo.svg ")
.then(r =>r.blob())
.then(async (img) => {
const base64 = btoa(
await img.text()
)
console.log(`<html>
<img src="data:image/svg+xml;base64,${base64}" />
</html>`)
})

When we run this, we get the expected output:

deno run --allow-net web-apis/fetch-deno-logo.js
Executing code to fetch Deno logo
Press + to interact
<html>
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMj
AwMC9zdmciIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiB2aWV3Qm94PSIwIDAgNTEyMCA1MTIwIj48d
Gl0bGU+RGVubyBsb2dvPC90aXRsZT48cGF0aCBkPSJNMjU2MCAwYTI1NjAgMjU2MCAwIDEgMSAwIDUxMj
AgMjU2MCAyNTYwIDAgMCAxIDAtNTEyMHoiLz48cGF0aCBmaWxsPSIjZmZmIiBkPSJNMjQ2MCAxNDQ5Yy03NDQgMC0xMzI0IDQ2OS0xMzI0IDEwNT
IgMCA1NTAgNTMzIDkwMSAxMzU5IDg4NGwyNS0xIDkxLTMtMjMgNjAgMyA2YTY2OCA2NjggMCAwIDEgMTggNDdsMiA2IDMgMTAgNCAxNCAzIDkgNCAxMCAzIDE
xIDQgMTYgNSAxNyAzIDExIDUgMTggNSAxOSA0IDE5IDUgMjAgNCAxNCA1IDIyIDUgMjIgNyAzMCAzIDE2IDUgMjQgNSAyNSA2IDI2IDcgMzcgNiAzMCA4IDQyIDQgMjEgNyAzMyA2IDM0IDggNDYgOSA0OCA4IDUwIDkgNTEgOSA1MiA5IDU0IDkgNTYgNyA0MyAxMSA3MyA1IDMwIDEyIDc3IDkgNjMgOCA0OCA5IDY2IDUgMzNjNTQ5LTczIDEwMzctMzM5IDEzOTMtNzI4bDExLTEyLTUxLTE5MC0xMzUtNTA1LTg0LTMxNC03NC0yNzYtNDYtMTY4LTI5LTEwNi0xNy02NC0xNi01Ni02LTI0LTQtMTMtMi03LTItNmMtNzgtMjUxLTIyOS00NzMtNDM1LTYzNC0yNDItMTg5LTU0OS0yODgtOTA3LTI4OHptLTY1NCAyNjY5Yy02NS0xOC0xMzMgMjAtMTUyIDg1bC0xIDMtMTEyIDQxNmEyMjg3IDIyODcgMCAwIDAgMjE1IDkzbDE3IDcgMTIxL
TQ1MSAxLTNjMTYtNjYtMjMtMTMzLTg5LTE1MHptNjk3LTMwNWMtNjYtMTgtMTM0IDIwLTE1MyA4NWw
tMSAzLTE3MCA2MzB2M2ExMjUgMTI1IDAgMCAwIDI0MSA2NWwxLTMgMTcwLTYzMHYtM2wzLTE0IDEtNS
00LTIxLTYtMjktNC0xOGExMjUgMTI1IDAgMCAwLTc4LTYzem0tMTE4NS02NDktOCAxOS0xIDQtMTcwIDYzMC0xIDNhMTI1IDEyNSAwIDAgMCAyNDEgNjZsMS0zIDE1NC01NzJjLTgwLTQyLTE1My05Mi0yMTYtMTQ3em0tNDA1LTcyNWMtNjYtMTctMTM0IDIxLTE1MyA4NWwtMSAzLTE3MCA2MzB2M2ExMjUgMTI1IDAgMCAwIDI0MSA2NmwxLTMgMTcwLTYzMHYtM2MxNi02Ni0yMy0xMzMtODgtMTUxem0zODExLTE0M2MtNjUtMTctMTMzIDIxLTE1MiA4NWwtMSAzLTE3MCA2MzAtMSAzYTEyNSAxMjUgMCAwIDAgMjQyIDY2di0zbDE3MS02MzB2LTRjMTYtNjUtMjMtMTMyLTg5LTE1MHpNNTQyIDE0NTVhMjI4NCAyMjg0IDAgMCAwLTI2NyA4MzggMTI0IDEyNCAwIDAgMCA2MiAzOGM2NSAxNyAxMzMtMjEgMTUyLTg1bDEtMyAxNzAtNjMwIDEtM2MxNi02Ni0yMy0xMzMtODktMTUxYTEyNyAxMjcgMCAwIDAtMzAtNHptMzc1MiA0Yy02Ni0xNy0xMzMgMjEtMTUzIDg1djNsLTE3MCA2MzAtMSAzYTEyNSAxMjUgMCAwIDAgMjQxIDY2bDEtMyAxNzAtNjMwIDEtM2MxNi02Ni0yNC0xMzMtODktMTUxeiIvPjxwYXRoIGQ9Ik0yNjIwIDE4NzBhMTYwIDE2MCAwIDEgMSAwIDMyMCAxNjAgMTYwIDAgMCAxIDAtMzIweiIvPjxwYXRoIGZpbGw9IiNmZmYiIGQ9Ik0xMjgyIDg2MGMtNjUtMTctMTMzIDIxLTE1MiA4NWwtMSAzLTE3MCA2MzAtMSAzYTEyNSAxMjUgMCAwIDAgMjQxIDY2bDEtMyAxNzAtNjMwIDEtNGMxNi02NS0yMy0xMzItODktMTUwem0yMTg1IDExOWMtNjYtMTctMTM0IDIxLTE1MyA4NWwtMSAzLTExNCA0MjRhMTM5OSAxMzk5IDAgMCAxIDIxMSAxMjhsMTEgOSAxMzQtNDk1di0zYzE2LTY2LTIzLTEzMy04OC0xNTF6TTIzNTUgMjY5YTIyOTkgMjI5OSAwIDAgMC0yMzggMzRsLTE3IDMtMTU4IDU4Ny0xIDNhMTI1IDEyNSAwIDAgMCAyNDEgNjVsMS0zIDE3MC02MzAgMS0zYTEyNCAxMjQgMCAwIDAgMS01NnptMTU2NCA0MzUtMzMgMTI0LTEgM2ExMjUgMTI1IDAgMCAwIDI0MSA2NWwxLTMgNC0xM2EyMzEyIDIzMTIgMCAwIDAtMTk3LTE2NWwtMTUtMTF6bS05ODktNDE0LTYwIDIyMy0xIDNhMTI1IDEyNSAwIDAgMCAyNDEgNjVsMS0zIDYzLTIzNWEyMjg2IDIyODYgMCAwIDAtMjI2LTUwbC0xOC0zeiIvPjwvc3ZnPg==" />
</html>

Now, with the help of *nix output redirection features, we can create an HTML file with the output of our script:

deno run --allow-net web-apis/fetch-deno-logo.js > web-apis/deno-logo.html

We can now inspect the file.

Note: Use the ls command to see the web-apis folder in the directory. Use the cd command to move to the web-apis folder. There we can find the deno-logo.html file.

It's also possible to directly run a script from the Deno standard library to serve the current folder:

deno run --allow-net --allow-read https://deno.land/std@0.83.0/http/file_server.ts web-apis

The command above will show the output as follows:

Press + to interact
Check https://deno.land/std@0.65.0/http/file_server.ts
HTTP server listening on http://0.0.0.0:4507

Practice the commands in the widget provided below by clicking “Run” and typing the commands in the terminal.

Please execute the commands above in the same order they are written. By navigating to the link provided under the “Run” button of the widget and navigating to /deno-logo.html, we can check that the image is there and working.

fetch("https://deno.land/logo.svg")
  .then((r) => r.blob())
  .then(async (img) => {
    const base64 = btoa(await img.text());

    console.log(`<html>
<img src="data:image/svg+xml;base64,${base64}" />
</html>
  `);
  });
Fetch text from Deno's logo

Clicking the deno-logo.html file will show the following output:

Press + to interact
Accessing a web page with the Deno.land logo as a base64 image
Accessing a web page with the Deno.land logo as a base64 image

These are just examples of Web APIs that are supported in Deno. In this specific example, we’ve used fetch and btoa, but more will be used throughout the chapter.

Feel free to experiment with these already familiar APIs, either by writing simple scripts or by using the REPL. In the rest of the course, we’ll use known functions from the Web APIs.