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.
–
–
–
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));
–
–
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 ]
–
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.