-1

In the below script I need to implement a Promise for listSpaces() as it uses axios to fetch data externally.

Reading this I don't understand

If the condition is met, the Promise will be resolved, otherwise it will be rejected

In my case listSpaces() can either return an empty array or an array with elements.

Question

What condition is it he speaks of? And how can that be tied to my listSpaces()?

#!/usr/bin/env node

const yargs = require('yargs');
const listSpaces = require('./functions/cmdListSpaces');

yargs.command({
  command: 'list-spaces',
  describe: 'List spaces',
  type: 'boolean',
  handler(argv) {
    const a = listSpaces();
    a.forEach((v) => {
      console.log(v);
    });
  },
}).argv;

listSpaces()

const toml = require('./toml');
const config = toml('config/kibana.toml');
const axios = require('axios');
    
module.exports = async () => {
  const r = await axios({
    method: 'get',
    url: `${config.Url}api/spaces/space`,
    auth: {
      username: config.Username,
      password: config.Password,
    },
    headers: { 'kbn-xsrf': true },
  })
    .then(response => {
      let a = [];
      response.data.forEach((v) => {
        a.push(v.id);
      });
      return a;
    })
    .catch(error => {
        return error.response.data.statusCode;
  });
};
Sandra Schlichting
  • 25,050
  • 33
  • 110
  • 162
  • 1
    _"What condition is it he speaks of?"_ - The condition in his pseudo code that comes directly after that line of text o.O The condition that determines if the `resolve()` or the `reject()` callback should be executed. – Andreas Jun 24 '21 at 12:54
  • i don't think you'd need to use `.then` and `await` together like that.... you could simply do : `const r = await axios.get(...); ` and in the next line, without `then`, you could just do `r.data.foreach` – tsamridh86 Jun 24 '21 at 12:55
  • @Andreas Would that be the output from `listSpaces()` in my case? – Sandra Schlichting Jun 24 '21 at 12:58
  • 1
    "*[Reading this](https://www.freecodecamp.org/news/javascript-es6-promises-for-beginners-resolve-reject-and-chaining-explained/)*" - that's a pretty horrible article. It doesn't even use [the proper terminology for promises](https://stackoverflow.com/q/29268569/1048572). – Bergi Jun 24 '21 at 12:58
  • 1
    "*And how can that be tied to my `listSpaces()`?*" - not at all. You are not using the promise constructor, you don't have to check a condition to decide whether you want to call `resolve` or `reject`. – Bergi Jun 24 '21 at 13:00
  • 1
    "*In my case `listSpaces()` can either return an empty array or an array with elements*" - actually, it doesn't. It can also return a status code. You probably want to `throw` a `new Error` with the status code and message instead. – Bergi Jun 24 '21 at 13:01
  • Let's make these comments an answer :-) – Bergi Jun 24 '21 at 13:04

1 Answers1

3

Reading this, I don't understand

That's a pretty horrible article. It doesn't even use the proper terminology for promises.

What condition is it he speaks of?

As @Andreas mentioned in the comment, he refers to the condition in his pseudo code that comes directly after that line of text.

And how can that be tied to my listSpaces()?

Not at all. You are not using the promise constructor, you don't have to check a condition to decide whether you want to call resolve or reject.

In my case listSpaces() can either return an empty array or an array with elements

Actually, it doesn't. It can also return a status code. You probably want to throw a new Error with the status code and message instead.

In the below script I need to implement a Promise for listSpaces()

You already did. The problem is with your command handler that doesn't expect this promise, and tries to call forEach on it.

Fixing the mentioned problems, you also should not mix then/catch syntax with async/await. Choosing the method syntax:

yargs.command({
  command: 'list-spaces',
  describe: 'List spaces',
  type: 'boolean',
  handler(argv) {
    listSpaces().then(a => {
//              ^^^^^^^^^^
      a.forEach((v) => {
        console.log(v);
      });
    });
  },
}).argv;

function listSpaces() { // no async here!
  return axios({
//^^^^^^
    method: 'get',
    url: `${config.Url}api/spaces/space`,
    auth: {
      username: config.Username,
      password: config.Password,
    },
    headers: { 'kbn-xsrf': true },
  }).then(response => {
    let a = [];
    response.data.forEach((v) => {
      a.push(v.id);
    });
    return a;
  }).catch(error => {
    throw new Error(error.response.data.statusCode);
  });
}

or async/await:

yargs.command({
  command: 'list-spaces',
  describe: 'List spaces',
  type: 'boolean',
  async handler(argv) {
//^^^^^
    const a = await listSpaces();
//            ^^^^^
    a.forEach((v) => {
      console.log(v);
    });
  },
}).argv;

async function listSpaces() {
  try {
    const response = await axios({
//  ^^^^^^^^^^^^^^^^^^^^^^
      method: 'get',
      url: `${config.Url}api/spaces/space`,
      auth: {
        username: config.Username,
        password: config.Password,
      },
      headers: { 'kbn-xsrf': true },
    });
    let a = [];
    response.data.forEach((v) => {
      a.push(v.id);
    });
    return a;
  } catch(error) {
//  ^^^^^^^^^^^^
    throw new Error(error.response.data.statusCode);
  }
}
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • In your first example where you `return axios` and later `return a` in `listSpaces()`. The first `return` is a promise (I suppose) and the second is the function output. So the function now makes two returns, where the first is "tagged" with "promise" so it isn't mixed up with the function output? – Sandra Schlichting Jun 24 '21 at 13:46
  • 1
    The first `return` returns the promise chain (the promise created by the `axios().then().catch()` chained calls) and is executed immediately during the `listSpaces()` call, the second `return` is inside the `then` callback and provides the value that the promise will be resolved with, and is executed later when the previous promise in the chain fulfills and the callback is run. – Bergi Jun 24 '21 at 14:05
  • If there were a `return` inside `catch()` would that also return to `then`? – Sandra Schlichting Jun 24 '21 at 14:08
  • @SandraSchlichting No, that would provide the value that the promise returned by `.catch()` is resolved with. (If the callback is actually executed. If the promise that `.catch()` was called on is fufilled, the result is just propagated to the returned promise). – Bergi Jun 25 '21 at 00:42