-1

I have a promise which contains another API caller promise containing resolver. Now when I want to use the .then for parent promise, I am not able to do it, error says Cannot read property 'then' of undefined, below is my sample code

const getData = () => dispatch => new Promise((resolve) => {

  return apiService
    .getByParameter(abc)
    .then((data) => {
      dispatch(update({
        name: data.name
      }));

      resolve();
    })
    .catch(() => {
    });
});

Now whenever I try to do

this.getData().then({
<--something-->
});

It throws ne error as Cannot read property 'then' of undefined

the method getByParamter comes from a Class, as

getByParameter(...params) {
    const endpoint = `${this.getEndpoint.call(this, ...params)}`;
    const timeInitiated = performance.now();
    return request(() => axios.get(endpoint, extraHeaders), timeInitiated,
      endpoint, ACTIONS.ACTION_GET);
  }


const request = (rest, timeInitiated, endpoint, action) =>
  new Promise((resolve, reject) => {
    rest().then(({ data }) => {
      const timeResolved = performance.now();
      const timeCalculated = millisToMinutesAndSeconds(timeResolved - timeInitiated);

      if (endpoint !== LOGS_ENDPOINT && timeCalculated > MAX_EXECUTION_TIME) {
        apiLogger.warn(`The endpoint ${endpoint} took ${timeCalculated} seconds for ${action}`);
      }
      resolve(data);
    })
      .catch((response) => {
        if (!isCancel(response)) {
          reject(response);
        } else {
          apiLogger.debug('Request cancelled');
        }
      });
  });

Please suggest what should be the solution to achieve what I need.

Noob
  • 45
  • 3
  • 9
  • 8
    Don't use the promise constructor when promises already exist - it's called https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it – Benjamin Gruenbaum Dec 04 '20 at 20:11
  • the `getData()` method has no return. But your code is a promise anti pattern. – Randy Casburn Dec 04 '20 at 20:21
  • @BenjaminGruenbaum does this mean, chaining the promises is the way I should be doing it? – Noob Dec 04 '20 at 20:21
  • @RandyCasburn I tried putting resolve at the end, but that part of code is unreachable... – Noob Dec 04 '20 at 20:22
  • But wouldnt the Redux-Thunk follows the Antipattern?? as originally my getData method is an action with a dispatcher within... updating my code for wider picture – Noob Dec 04 '20 at 20:25
  • `this.getData()` returns a function. You have to call that function to get the promise or remove the extra level of function (since there's no obvious reason for it visible here). And, fix your promise anti-pattern. – jfriend00 Dec 04 '20 at 20:31
  • @Noob Now that you show more of the code, you have revealed that the anti-pattern is prevalent across likely all of your code. –  Dec 04 '20 at 20:48

2 Answers2

2

Your arrow function immediately, and unconditionally returns another function, not a promise!

const getData = () => (dispatch => new Promise(...))

getData() is a function, so .then does not exist on it.

Try it yourself

console.assert(typeof getData() !== "function", "`.then` doesn't exist on a function");

Honestly, this code ought to remove the dispatch callback and let the callee use a .then handler, that's what promises are for.

const getData = async () => {
    const data = await apiService.getByParameter(abc);

    return update(data);
});
  • updated my code for what is within getByParamter – Noob Dec 04 '20 at 20:37
  • @Noob well *now* we need to know whether or not `request` returns a promise. You'll have to follow the entire control flow chain to find out whether or not a promise is returned. –  Dec 04 '20 at 20:40
  • Yes it does, with `then` on () => axios.get(endpoint, extraHeaders) within, updated in question – Noob Dec 04 '20 at 20:42
  • Updated after realizing what Stuck said. –  Dec 04 '20 at 21:05
0

getData returns a function that expects a dispatch paramter. If you call that function then you get a promise.

const dispatch = useDispatch();
const myPromise = this.getData()(dispatch);

Note the empty brakets in the last line followed by the call with dispatch as argument ()(dispatch)

In other words getData creates a thunk that you can use to create the promise.

const thunkFunction = getData();
const myPromise = thunkFunction(dispatch);
myPromise.then(...)
Stuck
  • 11,225
  • 11
  • 59
  • 104