Why is my promise returning undefined?

前端 未结 2 1859
感情败类
感情败类 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: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);

提交回复
热议问题