bhylu.com

Advertisements

AngularJS $q Promises

A promise represents a value or failure that becomes available later. AngularJS $q integrates its callbacks with framework update scheduling, which matters when a callback changes a bound model.

How it works

The local inspection result resolves through $q.when. The controller exposes a pending state and then reports the resolved message. No actual network service is contacted. An expected refusal should remain distinguishable from success, and the caller should own both the returned promise and its failure path instead of starting work that nobody observes.

Run the code

AngularJS 1.8.3 is a legacy framework whose official support ended in January 2022. These examples teach maintenance, not a recommendation for a new application. They need a separate local browser page; Bhylu has no AngularJS playground.

In an empty folder save the HTML below as promises.html and the server as lab-server.mjs. Make a vendor folder and save the four pinned libraries there, retaining their MIT notices. With Node 22 or later run node lab-server.mjs promises.html, then open http://127.0.0.1:8136/. Stop that lab before running a different lesson. The server supplies fixed read-only HTTP fixtures; no data is saved and it does not connect to SQL. No PHP, Apache or MySQL configuration changes are needed.

Example

promises.html

<!doctype html>
<html lang="en" ng-app="repairLab" ng-strict-di>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <title>AngularJS $q Promises</title>
    <style>
      :root {
        font:
          18px/1.55 system-ui,
          sans-serif;
        color: #0f3464;
        background: #fff;
        color-scheme: light;
      }
      * {
        box-sizing: border-box;
      }
      body {
        margin: 0;
      }
      main {
        max-width: 50rem;
        margin: auto;
        padding: 1.2rem;
      }
      h1 {
        font-size: 1.65rem;
      }
      label {
        display: block;
        margin: 0.6rem 0;
      }
      input,
      select,
      textarea,
      button {
        font: inherit;
        max-width: 100%;
        padding: 0.35rem;
        margin: 0.2rem;
      }
      button {
        border: 1px solid #034fa0;
        border-radius: 0.25rem;
        background: #034fa0;
        color: white;
      }
      button:disabled {
        opacity: 0.55;
      }
      output,
      [role="status"] {
        display: block;
        min-height: 1.5rem;
      }
      table {
        border-collapse: collapse;
        width: 100%;
      }
      td,
      th {
        padding: 0.4rem;
        border: 1px solid #a5bbd4;
        text-align: left;
      }
      pre {
        white-space: pre-wrap;
        overflow-wrap: anywhere;
      }
      :focus-visible {
        outline: 3px solid #0078d4;
        outline-offset: 3px;
      }
      [ng-cloak] {
        display: none !important;
      }
      .marked {
        font-weight: 700;
      }
      .error {
        color: #a02424;
      }
      :root[data-theme="dark"] {
        color: #d6e7fb;
        background: #061d30;
        color-scheme: dark;
      }
      :root[data-theme="dark"] .error {
        color: #ffb4b4;
      }
    </style>
  </head>
  <body>
    <main ng-controller="DeskController as vm" ng-cloak>
      <h1>Community repair desk</h1>
      <p>AngularJS 1.8.3 · Legacy maintenance lab · Local demonstration</p>
      <button type="button" ng-click="vm.inspect()">Inspect fixture</button>
      <p data-result>{{ vm.message }}</p>
    </main>
    <script src="/vendor/angular.min.js"></script>
    <script>
      (function () {
        "use strict";
        var app = angular.module("repairLab", []);
        app.controller("DeskController", [
          "$q",
          function ($q) {
            var vm = this;
            vm.message = "Not started";
            vm.inspect = function () {
              vm.message = "Pending";
              return $q.when("Inspection preview ready").then(
                function (message) {
                  vm.message = message;
                },
                function () {
                  vm.message = "Inspection failed";
                },
              );
            };
          },
        ]);
      })();
    </script>
  </body>
</html>

Focus on the bindings and controller

This excerpt leaves out the document shell, styles and library files. Use the complete download to run it.


<button type="button" ng-click="vm.inspect()">Inspect fixture</button>
<p data-result>{{ vm.message }}</p>
<script>
  (function () {
    "use strict";
    var app = angular.module("repairLab", []);
    app.controller("DeskController", [
      "$q",
      function ($q) {
        var vm = this;
        vm.message = "Not started";
        vm.inspect = function () {
          vm.message = "Pending";
          return $q.when("Inspection preview ready").then(
            function (message) {
              vm.message = message;
            },
            function () {
              vm.message = "Inspection failed";
            },
          );
        };
      },
    ]);
  })();
</script>

Expected result

Not started

The result becomes Inspection preview ready after the promise callback runs. The browser test waits for that actual state, while the unit fixture drives the digest deliberately. Native promises or external callbacks do not automatically have the same AngularJS scheduling contract.

Advertisements