Search code examples
javascriptes6-promise

How to use requestAnimationFrame with Promise


I want to use requestAnimationFrame with Promise, so I can use it this way

opacityToggle("layername",0).then(i=>"do some stuff after animation ends")

, but not sure how to do this. Here is my code:

function opacityToggle(layerName, opacity) {

    if (!layerName) return;
    var requestID;
    var s = 0;
   
    return animate().then(i => i)

    function animate() {
        requestID = requestAnimationFrame(animate);
        if (s < 1) {
            s += 0.01
            s = +s.toFixed(2)
            console.log('s', layerName, s, opacity);
            map.setPaintProperty(layerName, 'fill-opacity', s);
        } else {
            cancelAnimationFrame(requestID);
            return new Promise(resolve => resolve)
        }
    }
}


Solution

  • While @Terry has the simple solution of wrapping just everything in the promise constructor, you get the real power of promises if you promisify only the requestAnimationFrame call itself:

    async function opacityToggle(layerName, opacity) { /*
    ^^^^^ */
        if (!layerName) return;
    
        var s = 0;
        while (s < 1) {
    //  ^^^^^
            s += 0.01
            s = +s.toFixed(2)
            console.log('s', layerName, s, opacity);
            map.setPaintProperty(layerName, 'fill-opacity', s);
    
            await new Promise(resolve => {
    //      ^^^^^
                requestAnimationFrame(resolve);
    //          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
            });
        }
    }
    

    If you can't use async/await and/or want to do it with the recursive approach, it would be

    function opacityToggle(layerName, opacity) {
        if (!layerName) return Promise.resolve();
    
        var s = 0;
        return animate();
    
        function animate() {
            if (s < 1) {
                s += 0.01
                s = +s.toFixed(2)
                console.log('s', layerName, s, opacity);
                map.setPaintProperty(layerName, 'fill-opacity', s);
                return new Promise(resolve => {
    //          ^^^^^^
                    requestAnimationFrame(resolve);
                }).then(animate);
    //            ^^^^^^^^^^^^^^
            } else {
                return Promise.resolve();
            }
        }
    }