Problem with promise and @@iterator in Javascript

Viewed 5213

I am new with the Promise object. When I run the code below in NodeJS

function solution(num){
    return getData(num).then(getMax); 
}

function getData(num){
    return Promise.resolve({
        first: 80 * num,
        second: 30 * num
    });
}

function getMax(numbers){
    return Promise.resolve(Math.max(...numbers));
}

solution(10)

I face the error

(node:7814) UnhandledPromiseRejectionWarning: TypeError: Found non-callable @@iterator at getMax

Could you help me to fix it? Thanks

3 Answers

you are doing ...numbers which expects numbers to be iterable , but in your case it is object

try making it an array ( or any iterable ) and it should work

function solution(num){
    return getData(num).then(getMax); 
}


function getData(num){
    return Promise.resolve([80 * num, 30 * num]);
}

function getMax(numbers){
    return Promise.resolve(Math.max(...numbers));
}

solution(10).then(console.log)

please read this comment if you want to fix your original code

You can fix your iterator error by using a generator function. JavaScript Objects, unlike Arrays, Sets, and Maps to name a few, do not come with a Symbol.iterator property. Many built-in functions, including Math.max will recognize an iterator based on the Symbol.iterator property. You can convert an object to an iterator by using a generator of its values.

function solution(num){
  return getData(num).then(getObjectValuesIterator).then(getMax);
}

function getObjectValuesIterator(obj){
  return (function*() {
    for (const key in obj) {
      yield obj[key]
    }
  })()
}

function getData(num){
    return Promise.resolve({
        first: 80 * num,
        second: 30 * num
    });
}

function getMax(numbers){
    return Promise.resolve(Math.max(...numbers));
}

solution(10).then(console.log) // => 800

getObjectValuesIterator returns an iterator based on a generator function. Math.max recognizes the iterator and does not error.

You see the problem here is:

return getData(num).then(getMax); 

In this case the successful callback from getData will return an object and you are passing that object into getMax.

The correct way here is:

return getData(num).then((result) => getMax(Object.values(result)); 
Related