ES6 Promises have a curious ability to accurately retrieve values from custom JavaScript objects

I have developed a unique library that functions independently from the Promise API, yet achieves similar objectives. It utilizes window.requestAnimationFrame and fallbacks to setTimeout, having no similarities with Promises. Interestingly, it is compatible with older systems such as ie9 - 10 or machines from 2009. You can find the source code here.

Surprisingly, the following code operates smoothly, enabling the 2nd promise to transmit the value (v + 3) correctly to the 3rd promise after a delay of 10 seconds. This is due to rafx.async... returning a custom proprietary object.

const x = Promise.resolve()
.then(() => console.log("2nd promise"))
.then(() => {
  //600 frames === 10 secs
  return rafx.async(6)
  .skipFrames(600)
  .then(v => v + 1)
  .then(v => v + 3);
});

console.log(x instanceof Promise);

x.then(v => console.log("3rd promise", v));
<script src="https://cdn.jsdelivr.net/npm/rafx"></script>

The expected outcome at x.then(v...) should align with whatever custom object is returned from the custom then method.

This is the result of rafx.async(6).skipFrames(600)...then(v => v + 3):

prt.Thenable {....
    status: Status {thenable: prt.Thenable, instance: Rafx...
    _argObj: {value: 10, done: true},
    _breaker: {value: false}
    ....

The constructors Thenable and Status are completely distinct from Promises, being entirely customized.

To my surprise, this even works:

const x = Promise.resolve()
.then(() => console.log("2nd promise"))
.then(() => {
  return rafx.async("hello")
  .loop(function(str){
    return str;
  })
  .until(str => window.testVar === " world!")
  .then(str => str + window.testVar);
});

console.log(x instanceof Promise);

x.then((value) => console.log("3rd promise", value))
.catch((e) => console.log(e));
<script src="https://cdn.jsdelivr.net/npm/rafx"></script>
<button onclick="window.testVar = ' world!';">set testVar to ' world!'</button>

You can confirm that Promise.prototype.then !== rafx.Thenable.prototype.then, indicating complete separation in implementation, as shown here;

How does Promise comprehend the functionality of my API? (I must be overlooking something obvious)

PS: I replaced all arrow functions (due to this binding) with regular ones, and it still functions, albeit against expectations..

Answer №1

The Promises specification is created in a way that allows it to function alongside other "thenables", which are objects with a .then property that is a function. If you resolve a promise with a thenable (such as by returning a thenable within a .then block), the outer promise will execute that function, passing in a resolve and reject function, and will wait for the inner thenable to invoke resolve before resolving itself.

For instance:

const promise = new Promise((resolve, reject) => {
  const myThenable = {
    then: (resolve2, reject2) => {
      console.log('running .then')
      setTimeout(() => {
        console.log('resolving inner');
        resolve2("hello");
      }, 1000)
    }
  }

  console.log('resolving outer');
  resolve(myThenable);
})

promise.then(result => {
  console.log('final result', result);
})

The code you've implemented for your thenable may not have been intended for this purpose, but it seems to be functioning correctly:

prt.Thenable.prototype.then = function(f, rest){

When the promise triggers your .then function, f acts as the resolve function, while rest serves as the reject function. At some point, you call f, which coincidentally behaves as needed, without causing any unexpected exceptions when rest turns out to be a different function than anticipated.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Custom palette in Material UI design palette allows users to create

Hey there everyone! I've been working on a website using ReactJS and Material UI, starting with this cool template. One thing I'm trying to do is change the color of the TextField when it's focused. Right now it's blue, but I want it ...

What is the significance of using the "why" in the href property within the

I need help understanding why the plus "+" is used before and after myUrl in the function .not. Even though it works fine with or without the +, I am curious about why it was included in the code snippet. <script type="text/javascript"> $(documen ...

Can WikiData be accessed by providing a random pageId?

My current project involves creating a Wikipedia Search App with a 'Feel Lucky' button. I have been trying to figure out if it's possible to send a request for Wikidata using a specific pageid, similar to the code below: async function lucky ...

Navigate a first person simulation using three.js and control your movements with the keyboard arrow

To access my reference material, please go to http://jsfiddle.net/fYtwf/ Overview I am working on a basic 3D simulation using three.js where the camera is surrounded by cubes in three dimensions. These cubes serve as a visual guide to where the camera is ...

Is it possible to transfer .NET backend functions to a frontend framework like React or Vue for client-side execution?

For instance, imagine a scenario where there is a login page requiring a username and password to meet specific criteria for validation: the username must contain a capital 'A' and the password should be exactly 8 characters long. The challenge l ...

Issue: friends.js file contains an unexpected token "<" error after implementing express.static and modifying HTML content upon button click

On localhost:9000, I'm attempting to load home.html initially. However, when I try it with my current code, I encounter the error: friends.js:1 Uncaught SyntaxError: Unexpected token <. I'm unsure about the meaning of this error. Additionally, ...

Having trouble getting a ForEach loop to work within promises when using mongoose?

Hey everyone! I'm diving into the world of nodeJs and working on a project that involves pushing certain values into an array. Unfortunately, my code isn't behaving as expected, and I suspect it has something to do with promises. Here's the ...

Send a file using ajax with the help of JavaScript and PHP

Currently, I am looking to implement a method for uploading files using Ajax and JavaScript/PHP without having the page refresh. My initial thought is to use Ajax to send the file using xmlhttp.send(file) and then retrieve it in the PHP script, but I' ...

404 error occurs when AngularJS removes hash symbol from URLs

I successfully eliminated the hash from my Angular JS website using the following code snippet: $locationProvider.html5Mode(true); Now, the previously displayed URL has been replaced with . The issue I'm facing is that when I do a hard refresh (Ct ...

Simulated FileList for Angular 5 App Unit Testing

Imitation FileList In my pursuit of writing a unit test (Angular5), I have encountered the need for a FileList. Despite researching extensively, I have been unable to uncover any clues or solutions. I am starting to question whether this is even feasible ...

`Error encountered when JSONP script is returning incorrect MIME Type`

I am currently faced with the task of extracting data from a third-party feed that provides a JSON file. Unfortunately, I do not have access to the server to enable CORS, so after conducting some research I learned about using JSONP. When checking the Chro ...

javascript function not being invoked

Currently, I have incorporated the following HTML <html> <head> <Title>EBAY Search</title> </head> <script language="JavaScript" src="ajaxlib.js"></script> <body> Click here & ...

The Importance of Node JS Callback Functions

Struggling to grasp the concept of callbacks? Check out this code snippet for authentication using MySQL. function authenticate(username, password, callback) { var query = "SELECT * from mydb.users where username='" + username + "'and BINARY ...

When toggling between light and dark themes using the useMediaQuery hook, the Material-ui styling is being overridden

While working with next.js and material-ui, I encountered an issue where the theme would change based on user preference. However, when switching to light mode, the JSS Styles that I had set were being overwritten. This problem only seemed to occur in ligh ...

Integrate Arduino's capabilities with Johnny-Five within an HTML JavaScript document

As a beginner in the world of JavaScript, I set out to embark on a project involving turning on a connected LED on an Arduino board by simply pressing a button on an HTML page. After doing some research, I came across a JavaScript library called "johnny- ...

What specific files from the Kendo core are required for utilizing Mobile and Angular functionalities?

After browsing through similar questions, I couldn't find a solution. Currently, I am experimenting with Kendo (open source core for now) in a Visual Studio Cordova project. Initially, disregarding Cordova, I am focusing on setting up a basic view wit ...

Issue with AJAX loading functionality not functioning properly in Internet Explorer

For a project, I have a portfolio that I need to create. The front page consists of a div with a loader which determines the screen size upon landing and selects the content to be pulled in using ajax. The reason for this approach is due to the simplicity ...

In mvc.net 4, Ajax is only compatible with the httpGet method and not with httpPost

There are two methods, httpGet and httpPost, inside the Login action. Currently, when an ajax call is made, it only works with the httpGet method of Login. I would like it to work with the httpPost method of Login. Thank you in advance for your answer! ...

Guide on including a callback function in the renderCell columns of Material UI X Datagrid

When a button is clicked and the redux action is successful, I am trying to use a simple toast hook to display a message in the parent component where my Data grid is located. Can a callback be passed to utilize this hook from within the data grid? Here i ...

Challenges arise when attempting to authenticate a user with password.js

Currently, I am working on implementing validation using passport.js and ES6. Below is the validation function that I have created: passport.use(new BasicStrategy( function(login, password, callback) { User.findOne({ login: login }).select(&a ...