Recursive Promise in javascript

前端 未结 6 1662
没有蜡笔的小新
没有蜡笔的小新 2020-12-08 01:58

I\'m writing a Javascript Promise that finds the final redirect URL of a link.

What I\'m doing is making a HEAD request in a Promise<

6条回答
  •  北海茫月
    2020-12-08 02:54

    The following has two functions:

    • _getRedirectUrl - which is a setTimeout object simulation for looking up a single step lookup of a redirected URL (this is equivalent to a single instance of your XMLHttpRequest HEAD request)
    • getRedirectUrl - which is recursive calls Promises to lookup the redirect URL

    The secret sauce is the sub Promise whose's successful completion will trigger a call to resolve() from the parent promise.

    function _getRedirectUrl( url ) {
        return new Promise( function (resolve) {
            const redirectUrl = {
                "https://mary"   : "https://had",
                "https://had"    : "https://a",
                "https://a"      : "https://little",
                "https://little" : "https://lamb",
            }[ url ];
            setTimeout( resolve, 500, redirectUrl || url );
        } );
    }
    
    function getRedirectUrl( url ) {
        return new Promise( function (resolve) {
            console.log("* url: ", url );
            _getRedirectUrl( url ).then( function (redirectUrl) {
                // console.log( "* redirectUrl: ", redirectUrl );
                if ( url === redirectUrl ) {
                    resolve( url );
                    return;
                }
                getRedirectUrl( redirectUrl ).then( resolve );
            } );
        } );
    }
    
    function run() {
        let inputUrl = $( "#inputUrl" ).val();
        console.log( "inputUrl: ", inputUrl );
        $( "#inputUrl" ).prop( "disabled", true );
        $( "#runButton" ).prop( "disabled", true );
        $( "#outputLabel" ).text( "" );
        
        getRedirectUrl( inputUrl )
        .then( function ( data ) {
            console.log( "output: ", data);
            $( "#inputUrl" ).prop( "disabled", false );
            $( "#runButton" ).prop( "disabled", false );
            $( "#outputLabel").text( data );
        } );
    
    }
    
    
    Input:
    
    
    
    Output:
    
    
    
    

    As another illustration of recursive Promises, I used it to solve a maze. The Solve() function is invoked recursively to advance one step in a solution to a maze, else it backtracks when it encounters a dead end. The setTimeout function is used to set the animation of the solution to 100ms per frame (i.e. 10hz frame rate).

    const MazeWidth = 9
    const MazeHeight = 9
    
    let Maze = [
        "# #######",
        "#   #   #",
        "# ### # #",
        "# #   # #",
        "# # # ###",
        "#   # # #",
        "# ### # #",
        "#   #   #",
        "####### #"
    ].map(line => line.split(''));
    
    const Wall = '#'
    const Free = ' '
    const SomeDude = '*'
    
    const StartingPoint = [1, 0]
    const EndingPoint = [7, 8]
    
    function PrintDaMaze()
    {
        //Maze.forEach(line => console.log(line.join('')))
        let txt = Maze.reduce((p, c) => p += c.join('') + '\n', '')
        let html = txt.replace(/[*]/g, c => '*')
        $('#mazeOutput').html(html)
    }
    
    function Solve(X, Y) {
    
        return new Promise( function (resolve) {
        
            if ( X < 0 || X >= MazeWidth || Y < 0 || Y >= MazeHeight ) {
                resolve( false );
                return;
            }
            
            if ( Maze[Y][X] !== Free ) {
                resolve( false );
                return;
            }
    
            setTimeout( function () {
            
                // Make the move (if it's wrong, we will backtrack later)
                Maze[Y][X] = SomeDude;
                PrintDaMaze()
    
                // Check if we have reached our goal.
                if (X == EndingPoint[0] && Y == EndingPoint[1]) {
                    resolve(true);
                    return;
                }
    
                // Recursively search for our goal.
                Solve(X - 1, Y)
                .then( function (solved) {
                    if (solved) return Promise.resolve(solved);
                    return Solve(X + 1, Y);
                } )
                .then( function (solved) {
                    if (solved) return Promise.resolve(solved);
                    return Solve(X, Y - 1);
                 } )
                 .then( function (solved) {
                    if (solved) return Promise.resolve(solved);
                    return Solve(X, Y + 1);
                 } )
                 .then( function (solved) {
                     if (solved) {
                         resolve(true);
                         return;
                     }
    
                     // Backtrack
                     setTimeout( function () {
                         Maze[Y][X] = Free;
                         PrintDaMaze()
                         resolve(false);
                     }, 100);
                     
                 } );
    
            }, 100 );
        } );
    }
    
    Solve(StartingPoint[0], StartingPoint[1])
    .then( function (solved) {
        if (solved) {
            console.log("Solved!")
            PrintDaMaze()
        }
        else
        {
            console.log("Cannot solve. :-(")
        }
    } );
    
    
    

提交回复
热议问题