Attaching an Attribute to a Promise

Another question on SO sparked my interest in creating setTimeout

that returned Promise and timerId, but would not break backwards compatibility. This is the question I mean.

It just asks if the inner return statement in the method is _.delay

underscore.js

extraneous or serves a purpose. Here's a block of code.

This is the code for _.delay:

// Delays a function for the given number of milliseconds, and then calls
// it with the arguments supplied.
_.delay = function(func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function() { // this is to return the timerId
        return func.apply(null, args); // this guy right is in question
    }, wait);
};

      

Given that setTimeout does not currently return a Promise, I came up with an idea of โ€‹โ€‹what is possible for future validation if setTimeout returns a promise one day.

This setTimeout

requires the timerId to be returned so that it can be canceled. Therefore, in order to return a Promise

, you will need to bind timerId to a Promise in order to return a Promise and access the timer.

Then you can change clearTimeout

to do the same as now when the timerId is set, but for the Promise, it uses the Promise.timerId to clear the timeout and cancel the Promise. Of course, you will also need to refuse to cancel promises ...

Anyway ... I started working on something for fun and came across something I couldn't explain. If you run the snippet below, you can see that the promise has an attribute .timerId

before it is returned, but the attribute is missing after returning. Can anyone explain this?

function pseudoSetTimeout( func, wait ) {

    let timerId,
        promise = new Promise( ( resolve, reject ) => {
            timerId = setTimeout( () => {
                let returnVal = func();
                resolve( returnVal );
            }, wait );
        });

    promise.timerId = timerId;

    console.log( "promise before return: ", promise );

    return promise;
}

function callback() {
    return "Callback fired";
}

let timeout = pseudoSetTimeout( callback, 1000 )
    .then( ( val ) => {
      console.log( val );
    });

console.log( "returned promise: ", timeout );
      

Run codeHide result


+3


source to share


3 answers


then

in:

pseudoSetTimeout( callback, 1000 )
    .then( ( val ) => {
      console.log( val );
    });

      

returns a new promise that does not return pseudoSetTimeout

. This is a promise with undefined

the promised value as the callback then

does not return anything.

You can get it to work without applying then

at assignment time:



function pseudoSetTimeout( func, wait ) {

    let timerId,
        promise = new Promise( ( resolve, reject ) => {
            timerId = setTimeout( () => {
                let returnVal = func();
                resolve( returnVal );
            }, wait );
        });

    promise.timerId = timerId;

    console.log( "promise before return: ", promise );

    return promise;
}

function callback() {
    return "Callback fired";
}

let timeout = pseudoSetTimeout( callback, 1000 );
timeout.then( ( val ) => {
  console.log( val );
});

console.log( "returned promise: ", timeout );
      

Run codeHide result


Since it then

is critical when using promises and is often used to chain them, it seems like the idea of โ€‹โ€‹attaching a custom property to a promise loses its usefulness.

+4


source


A really interesting question.

Not sure how it's done inside node, but looking at the bluebird code, there is any indication: https://github.com/petkaantonov/bluebird/blob/master/src/thenables.js



My guess would be that the promise returned is actually a different object.

0


source


Due to the reasons mentioned in other answers, I would return a "tuple" instead of using the property as promised:

function pseudoSetTimeout( func, wait ) {
    let timerId,
        promise = new Promise( ( resolve, reject ) => {
            timerId = setTimeout( () => {
                let returnVal = func();
                resolve( returnVal );
            }, wait );
        });

    let result = [timerId, promise];
    console.log ( "returning: ", result );
    return result;
}

function callback() {
    return "Callback fired";
}

let [timeout, promise] = pseudoSetTimeout( callback, 1000 );

promise.then( ( val ) => {
   console.log( val );
});

console.log( "returned timeout: ", timeout );
      

Run codeHide result


0


source







All Articles