相关文章推荐
3vti1qhhvcgxwespkody  ·  js ...·  1 周前    · 
睿智的柿子  ·  Transactions with ...·  1 年前    · 
潇洒的葡萄  ·  Java开发利器Guava ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I've taken a look at a few questions on recursion in promises and am confused on how to implement them properly:

  • Recursive Promise in javascript
  • AngularJS, promise with recursive function
  • Chaining Promises recursively
  • Javascript Recursive Promise
  • I put together a simple example (see below) - this is just an example so I can understand how to make recursion with promises work and not a representation of the code in which I'm working.

    Net-net, I'd like the promise to resolve, but according to the output on node, it doesn't resolve. Any insight into how to make this resolve?

    var i = 0;
    var countToTen = function() { 
        return new Promise(function(resolve, reject) {
            if (i < 10) {
                console.log("i is now: " + i);
                return countToTen();
            else {
                resolve(i);
    countToTen().then(console.log("i ended up at: " + i));
    

    And the output on the console:

    > countToTen().then(console.log("i ended up at: " + i));
    i is now: 1
    i is now: 2
    i is now: 3
    i is now: 4
    i is now: 5
    i is now: 6
    i is now: 7
    i is now: 8
    i is now: 9
    i is now: 10
    i ended up at: 10
    Promise { <pending> }
    

    The promise never resolves.

    change return countToTen(); to resolve(countToTen()); - the console will still say "pending", however, if you instead say var p = countToten...... then you'll see p is resolved – Jaromanda X Mar 27, 2018 at 23:34 the other issue you have is that your .then is wrong ... .then expects a function as an argument, you have supplied undefined (the result of running console.log as an argument - which is why the output to the console looked OK to you – Jaromanda X Mar 27, 2018 at 23:35 Thank you @Jaromanda X, upvoted since you didn't write an answer, otherwise would have accepted yours. Appreciate the response. – joelc Mar 27, 2018 at 23:43

    If you look at your code as long as i is less than 10 you are recursing and never resolving the promise. You eventually resolve a promise. but it is not the promise the initial caller gets.

    You need to resolve with the promise returned by the recursion. How the system works if you resolve with a promise it will still not resolve until also the value is resolved:

    let i = 0;
    const countToTen = () => new Promise((resolve, reject) => {
        if (i < 10) {
          console.log("i is now: " + i);
          resolve(countToTen());
        } else {
          resolve(i);
    countToTen().then(() => console.log("i ended up at: " + i));
    you may want to also point out the incorrect usage of .then - since you changed that code too in your answer :p - because if .then was used correctly, OP would not have seen that final output – Jaromanda X Mar 27, 2018 at 23:39 Thanks alot it really hepled me ! i was going to ask a new question .... Just in time found this answer :-) really happy ..... – Sanmeet Dec 13, 2021 at 15:52 new Promise ((resolve, _) => from < to ? (console.log (from), resolve (countTo (to, from + 1))) : resolve (from)) countTo (7, 2) .then (console.log, console.error) // 2 3 4 5 6 7
    const asyncUnfold = async (f, init) =>
      f ( async (x, acc) => [ x, ...await asyncUnfold (f, acc) ]
        , async () => []
        , init
    const delay = (x, ms = 50) =>
      new Promise (r => setTimeout (r, ms, x))
    const countTo = (to, from = 0) =>
      asyncUnfold
        ( async (next, done, acc) =>
            acc <= to
              ? next (await delay (acc), await delay (acc + 1))
              : done ()
        , from
    countTo (10) .then (console.log, console.error)
    // [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
    countTo (7, 2) .then (console.log, console.error)
    // [ 2, 3, 4, 5, 6, 7 ]

    Here's a more practical example where we have a database of records and we wish to perform a recursive look-up, or something...

  • db.getChildren accepts a node id and returns only the node's immediate children

  • traverse accepts a node id and it recursively fetches all descendant children (in depth-first order)

  • const data =
      { 0 : [ 1, 2, 3 ]
      , 1 : [ 11, 12, 13 ]
      , 2 : [ 21, 22, 23 ]
      , 3 : [ 31, 32, 33 ]
      , 11 : [ 111, 112, 113 ]
      , 33 : [ 333 ]
      , 333 : [ 3333 ]
    const db =
      { getChildren : (id) =>
          delay (data [id] || [])
    const Empty =
      Symbol ()
    const traverse = (id) =>
      asyncUnfold
        ( async (next, done, [ id = Empty, ...rest ]) =>
            id === Empty
              ? done ()
              : next (id, [ ...await db.getChildren (id), ...rest ])
        , [ id ]
    traverse (0) .then (console.log, console.error)
    // [ 0, 1, 11, 111, 112, 113, 12, 13, 2, 21, 22, 23, 3, 31, 32, 33, 333, 3333 ]
    Thanks. It was just an example. "I put together a simple example (see below) - this is just an example so I can understand how to make recursion with promises work and not a representation of the code in which I'm working." – joelc Mar 28, 2018 at 15:00

    Many members already mentioned, need to resolve with the promise returned by the recursion.

    I would like to share code into async/await syntax.

    const printNumber = (i) => console.log("i is now: " + i);
    // recursive function to call number increment order
    const recursiveCallNumber = async (i, checkCondition) => {
        // if false return it, other wise continue to next step
        if (!checkCondition(i)) return;
        // then print
        printNumber(i); 
         // then call again for print next number
        recursiveCallNumber(++i, checkCondition);
    await recursiveCallNumber(1, (i) => i <= 10);
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.