Why is my promise returning undefined?

前端 未结 2 1851
感情败类
感情败类 2020-12-19 23:06

Background

I am trying to make a function that delays the execution of asynchronous functions by X ms.

For the purposes of this demonstration, the followi

相关标签:
2条回答
  • 2020-12-19 23:29

    Here's your problem:

            setTimeout(anUrl => {
                return new Promise( fulfil => {
                    fulfil(asyncMock(anUrl));
                });
            }, throttleMs, url);
    

    What you're doing here is you return a promise from the setTimeout callback. The return value of functions run by setTimeout are ignored so no one will get that value.

    0 讨论(0)
  • 2020-12-19 23:32

    Because throttleAsync returns the result of calling promise.then, and the then callback doesn't return anything. This makes the promise created by then resolve with the value undefined.

    You probably meant to have it return the new promise you're creating, but you're not doing that until the setTimeout callback. You want to do it prior (but there's more, keep reading):

    let throttleAsync = function(url) {
    
        return promise.then(() => {
            return new Promise( fulfil => {
                setTimeout(anUrl => {
                    fulfil(asyncMock(anUrl));
                }, throttleMs, url);
            });
        });
    };
    

    There's also no reason to pass the URL through setTimeout like that, so:

    let throttleAsync = function(url) {
    
        return promise.then(() => {
            return new Promise( fulfil => {
                setTimeout(() => {
                    fulfil(asyncMock(url));
                }, throttleMs);
            });
        });
    };
    

    Originally I though the promise there was unnecessary, but you've clarified that you want to ensure that repeated calls are "spaced out" by throttleMs. To do that, we'd use the above, but update promise:

    let throttleAsync = function(url) {
    
        return promise = promise.then(() => {
        //     ^^^^^^^^^
            return new Promise( fulfil => {
                setTimeout(() => {
                    fulfil(asyncMock(url));
                }, throttleMs);
            });
        });
    };
    

    This way, the next call to asyncThrottle will wait until the previous one has fired before starting the next.

    Live Example:

    const throttleMs = 1000;
    
    const asyncMock = url => url;
    
    let promise = Promise.resolve();
    
    let throttleAsync = function(url) {
    
        return promise = promise.then(() => {
        //     ^^^^^^^^^
            return new Promise( fulfil => {
                setTimeout(() => {
                    fulfil(asyncMock(url));
                }, throttleMs);
            });
        });
    };
    
    console.log('running');
    
    throttleAsync('http://www.bananas.pt')
        .then(console.log)
        .catch(console.error);
    
    throttleAsync('http://www.fruits.es')
        .then(console.log)
        .catch(console.error);
    
    throttleAsync('http://www.veggies.com')
        .then(console.log)
        .catch(console.error);

    0 讨论(0)
提交回复
热议问题