0

In this post it is mentioned that I can create a custom Promise with setTimeout like below:

const delay = t => new Promise(resolve => setTimeout(resolve, t));

My operation needs to be executed after 100ms so t will be 100 in my scenario.

I'm confused on how to use this though. The normal format of a Promise is new Promise (resolve, reject) but in the delay function only the resolve has been defined. Here's my attempt:

function numbersValidation(number1, number2) {
  if (!Number.isFinite(number1) || !Number.isFinite(number2)) {
    throw new Error('Only numbers are allowed');
  }
}

function add(number1, number2) {
  numbersValidation(number1, number2);
  return number1 + number2;
}

const addPromise = (number1, number2) => {
  delay(100)
  .then(result => result = add(number1, number2));
  .catch(err => reject(err));
};

// -----Test------

describe.only('promise calculator', () => {
  it('add works fine', done => {
    calculator.addPromise(1, 2).then(result => {
      try {
        assert.equal(3, result);
        done();
      } catch (e) {
        done(e);
      }
    });
  });
});
// AssertionError [ERR_ASSERTION]: 3 == false

This is quite wrong since my IDE is complaining about the structure, but can someone please point me in the right direction on how to use the delay function so that I make my addPromise function work? Thank you

kelsny
  • 23,009
  • 3
  • 19
  • 48
  • The delay arrow function is correct. Your IDE may be complaining because you have the `result` variable not used. – Franco Agustín Torres Oct 29 '22 at 16:41
  • If your IDE complains about "something" than you should ask your IDE what it is talking about. That said... Why do you need a `Promise()` at all? A `setTimeout(() => add(number1, number2), 100)` does the same (because `addPromise()` doesn't return anyhting) – Andreas Oct 29 '22 at 16:43
  • "*The normal format of a Promise is `new Promise (resolve, reject)`*" - no. "*but in the delay function only the resolve has been defined*" - so what? `setTimeout` doesn't cause any errors that would require you to reject the promise. So what errors do you want to handle? – Bergi Oct 29 '22 at 20:27
  • @Bergi what if the input is a string and the error `Only numbers are allowed` is thrown, isn't that an error that I need to catch? Wouldn't that fall in the `rejected` category of a Promise? – santa_cloudy Oct 29 '22 at 20:30
  • @santa_cloudy that's something to catch in `addPromise` or in your test, but not in the `delay` function. – Bergi Oct 29 '22 at 20:32

2 Answers2

0

throwing inside a .then will result in the Promise it's connected to rejecting, which is what you want. Just leave off your .catch(err => reject(err)); (since that part isn't needed at all, and reject isn't in scope there anyway).

const delay = ms => new Promise(res => setTimeout(res, ms));
function numbersValidation(number1, number2) {
  if (!Number.isFinite(number1) || !Number.isFinite(number2)) {
    throw new Error('Only numbers are allowed');
  }
}

function add(number1, number2) {
  numbersValidation(number1, number2);
  return number1 + number2;
}

const addPromise = (number1, number2) => (
  delay(100)
    .then(result => result = add(number1, number2))
);

addPromise(1, 2)
  .then((result) => {
    console.log('success:', result === 3);
  })
  .catch((error) => {
    console.log('error:', error.message);
  });

addPromise(4, 'abc')
  .then((result) => {
    console.log('success:', result);
  })
  .catch((error) => {
    console.log('error:', error.message);
  });
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • I think you need to add `===` after result. But the code doesn't pass my test, I added the test snippet, can you please take a look and identify why your code works here in SO but not passing my test? Thanks – santa_cloudy Oct 29 '22 at 17:23
  • `addPromise` is a standalone function, not a property of a `calculator` object. Calling `addPromise(1, 2)` produces a Promise that resolves to `3`. `result === 3` results in `true`. That's what you want, isn't it? If you want to call a `done` function when there's an error, then put that in the `.catch` handler (don't use `try`/`catch`, use `Promise.prototype.catch`) – CertainPerformance Oct 29 '22 at 17:27
  • my `addPromise` is extracted as an object, in order to be accessed from the `test.js` file using `calculator.addPromise`. Does this somehow affect the code structure my function should have? – santa_cloudy Oct 29 '22 at 17:32
  • 1
    You hadn't defined a `calculator` object before, so it seemed pretty suspicious - problems like those (defining something one way in a question, and in a different way in one's actual code) are frequent issues seen in Stack Overflow question. – CertainPerformance Oct 29 '22 at 17:35
  • `addPromise(1, 2)` produces a Promise that resolves to the number `3`. If that's what you want but it's still failing your test, either the test is faulty or the code has been miscopied, or something like that. As you can see from the snippet above, `result === 3` results in `true` – CertainPerformance Oct 29 '22 at 17:37
0

This is a working code that you can adapt to your settings.

import { strict as assert } from 'node:assert';
function numbersValidation(number1, number2) {
  if (!Number.isFinite(number1) || !Number.isFinite(number2)) {
    throw new Error('Only numbers are allowed');
  }
}

function add(number1, number2) {
  numbersValidation(number1, number2);
  return number1 + number2;
}
const delay = t => new Promise(resolve => setTimeout(resolve, t))
const addPromise = (number1, number2) => {
  return delay(100)
  .then(result => result = add(number1, number2))
  .catch(e => Promise.reject(e))
};


// addPromise(1, 'a').then(result => {
//   try {
//     assert.equal(3, result);
//   } catch (e) {
//     console.log(e)
//   }
// })

addPromise(1, 2)
  .then(result => {
      assert.equal(3, result)
  })
  .catch(e => console.log(e))

Problems:

  1. Typo in .then(result => result = add(number1, number2)); the ; needs to be removed.

  2. addPromise should return the promises made by delay, cuz you are calling then on calculator.addPromise(1, 2)

  3. Usually it is Promise.reject instead of reject, unless you expose it to the global context.

  4. It is better to use a chaining catch other than the catch in the comments code, you can catch exceptions in the callback of then

  5. the delayed promise only has resolve, cuz it doesn't need to reject, time will pass 100ms anyway unless our universe might be frozen and the delay will reject.

"No, I can't resolve, cuz time stopped".

sfy
  • 2,810
  • 1
  • 20
  • 22
  • Thanks a lot for your comments! The code still doesn't work for me, when I console log it shows me Promise { } and I think that's why I'm still getting AssertionError [ERR_ASSERTION]: 3 == false :/ – santa_cloudy Oct 29 '22 at 19:21
  • `.catch(e => Promise.reject(e))` is pointless, you should just omit that – Bergi Oct 29 '22 at 20:28
  • @Bergi It is just a demonstration that we can catch errors from `numbersValidation`, but we don't handle it and reject it to the upper level. – sfy Oct 30 '22 at 04:28
  • @santa_cloudy That means the promise has not been resolved yet, ensure the assertion is in the `then` 's callback. – sfy Oct 30 '22 at 04:33