Mio
Mio

Reputation: 1502

Resolve nested promises

I would like to know how I can deal with parameter nested promise.

I have this kind of code :

'use strict';

function fetchData(tableName) {
  new Promise((resolve, reject) => {
    if (tableName === 'tableName2') {
      setTimeout(reject, 200, tableName);
    } else {
      setTimeout(resolve, 200, tableName);
    }
  });
}

function notifyUser(data) {
  console.log(data); // get only undefined 3 times
  new Promise((resolve) => {
    setTimeout(resolve, 200, data);
  });
}

let cont = { fail: () => '', success: () => console.log };
function verifyAndNotify(context) {
  let actions = [];
  ['tableName1','tableName2','tableName3'].map(tableName => {
    actions.push(notifyUser(fetchData(tableName))); // how to deal with this???
  });

  Promise.all(actions)
    .then(success => {
      console.log(`All is ok ${success}`);
    }).catch(error => {
      console.log(`error with: ${error}`);
      errors.push(error);
    });

  if (errors.lenght > 0) {
    return context.fail(`Errors: ${errors}`);
  } else {
    return context.success(`Success`);
  }
}

verifyAndNotify(cont);

The problem is I need to resolve the param before giving it to the method. I probably mix few things I very bad at JS.

I would like to notify the user with each tableName and I would like to raise an error if one the "table" actions failed (fetching data or notify).

EDIT 1:

First working version after comments and answer:

'use strict';

function fetchData(tableName) {
  return new Promise((resolve, reject) => {
    if (tableName === 'tableName2') {
      setTimeout(reject, 200, tableName);
    } else {
      setTimeout(resolve, 200, tableName);
    }
  });
}

function notifyUser(data) {
  console.log(data);
  return new Promise((resolve) => {
    setTimeout(resolve, 200, data);
  });
}

const cont = { fail: (msg) => console.log('🌈' + msg), done: (msg) => console.log('🚨' + msg) };
function verifyAndNotify(context) {
  const errors = [];
  const actions = ['tableName1', 'tableName2', 'tableName3'].map(tableName =>
    fetchData(tableName).then(notifyUser).catch(error => {errors.push(error);}));

  Promise.all(actions)
    .then(success => {
      if (errors.length) throw errors;
      else {
        context.done(`Success ${success}`);
      }
    }).catch(errors => {
      context.fail(`Errors: ${errors}`);
    });
}

verifyAndNotify(cont);

Upvotes: 1

Views: 2591

Answers (1)

Brett Beatty
Brett Beatty

Reputation: 5963

As @Grundy said, the first problem is that your functions need to return the promises (return new Promise ...).

As far as your actions list goes, you might be looking to map your array to an array of promises:

const actions = ['tableName1', 'tableName2', 'tableName3'].map(tableName =>
    fetchData(tableName).then(notifyUser));

Also, you appear to want a list of each promise that had an error, in which case you'll want to add a catch to each action promise because Promise.all rejects as soon as one action rejects. For example:

const errors = [];
const actions = ['tableName1', 'tableName2', 'tableName3'].map(tableName =>
    fetchData(tableName).then(notifyUser).catch(errors.push));
Promise.all(actions)
    .then(success => {
        if (errors.length) throw errors;
        else {
            console.log(`All is ok ${success}`);
            context.done(`Success`);
        }
    }).catch(errors => {
        context.fail(`Errors: ${errors}`);
    });

Upvotes: 4

Related Questions