Do I Need to Return After Early Resolve/Reject

Do I need to return after early resolve/reject?

The return purpose is to terminate the execution of the function after the rejection, and prevent the execution of the code after it.

function divide(numerator, denominator) {
return new Promise((resolve, reject) => {

if (denominator === 0) {
reject("Cannot divide by 0");
return; // The function execution ends here
}

resolve(numerator / denominator);
});
}

In this case it prevents the resolve(numerator / denominator); from executing, which is not strictly needed. However, it's still preferable to terminate the execution to prevent a possible trap in the future. In addition, it's a good practice to prevent running code needlessly.

Background

A promise can be in one of 3 states:

  1. pending - initial state. From pending we can move to one of the other states
  2. fulfilled - successful operation
  3. rejected - failed operation

When a promise is fulfilled or rejected, it will stay in this state indefinitely (settled). So, rejecting a fulfilled promise or fulfilling a rejected promise, will have not effect.

This example snippet shows that although the promise was fulfilled after being rejected, it stayed rejected.

function divide(numerator, denominator) {  return new Promise((resolve, reject) => {    if (denominator === 0) {      reject("Cannot divide by 0");    }
resolve(numerator / denominator); });}
divide(5,0) .then((result) => console.log('result: ', result)) .catch((error) => console.log('error: ', error));

How to stop processing continuing past a promise reject

There's nothing special about invoking reject. It's just a function. If you want to bail on further processing, your function should return.

try {
imageBuffer = await retrieveImageFromURI(camera.ing_uri)
console.log(`Record #${i} Successful Ingestion from URI`);
} catch (err) {
console.log("Going to reject");
reject({ 'Task': `Attempting to pull image from camera (${camera.camName}`})
console.log("Rejected");
return;
}

should i use `return` in Promise?

There is no need to use a return statement inside a new Promise() callback. The Promise constructor is not expecting any sort of return value from the callback.

So, the reason to use a return statement inside that callback is only to control the flow of execution in that function. If you want execution inside your callback to finish and not execute any more code within that callback, you can issue a return; at that point.

For example, you could have written your code like this with no return statement:

function saveToTheDb(value) {  
return new Promise(function(resolve, reject) {
db.values.insert(value, function(err, user) {
if (err) {
reject(err);
} else {
resolve(user);
}
});
}
}

In this case, you used the if/else clause to make sure the flow of control in your function takes the correct path and no return was needed or used.


A common shortcut when promisifying async functions like this is:

function saveToTheDb(value) {  
return new Promise(function(resolve, reject) {
db.values.insert(value, function(err, user) {
if (err) return reject(err);
resolve(user);
});
}
}

This is not functionally different than the previous code block, but it is less typing and more compact. The return statement in front of reject(err); is only for flow of control reasons to prevent from executing the resolve(user); statement in case of error since the desired flow of control is to call reject(err) and then not execute anything else in the callback.


In fact, the return statement in this last block is not actually even needed in this specific case because executing a resolve() after a reject() will not do anything since promises are latched to whichever happens first resolve or reject. But, it is generally considered poor practice to execute unnecessary code so many would argue that it is better to use flow of control structures such as if/else or return to only execute the code that is needed.

So, this would technically work too, but is not considered a best practice because it executes unnecessary code and isn't as clearly structured:

function saveToTheDb(value) {  
return new Promise(function(resolve, reject) {
db.values.insert(value, function(err, user) {
if (err) reject(err);
resolve(user);
});
}
}

FYI, what you are doing here is called "promisifying" which makes a regular async function that works with a callback into a function that returns a promise. There are libraries and functions that will "promisify" a function or a whole object of functions (e.g. a whole API) for you in one function call so you don't have to do this manually. For example, I regularly use Bluebird which offers Promise.promisify() for promisifying a single function or Promise.promisifyAll() which will promisify all the methods on an object or prototype. This is very useful. For example, you could get promisified versions of the entire fs module with just this:

var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs'));

Then, you can use methods that return a promise such as:

fs.readFileAsync("file.txt").then(function(data) {
// do something with file.txt data here
});

Why does javascript ES6 Promises continue execution after a resolve?

JavaScript has the concept of "run to completion". Unless an error is thrown, a function is executed until a return statement or its end is reached. Other code outside of the function can't interfere with that (unless, again, an error is thrown).

If you want resolve() to exit your initializer function, you have to prepend it by return:

return new Promise(function(resolve, reject) {
return resolve();
console.log("Not doing more stuff after a return statement");
});

Why do I need an explicit return when a Promise is returned?

res.data() does return a promise, but if you simply leave it there it will be function existing in its own scope with no purpose. When you return that function, you can chain it to the next then.

Update - Expanding on the res.text()

res.text() is doing the following inside:

return new Promise((resolve, reject) => {
// Do something with your data and then
resolve(data)
})

Now, when you call res.text(), that is the value you receive back: a Promise object in the pending state. The Promise object is what you chain then and catch to. But if you don't return the Promise, your function will create a Promise but return nothing. So when you use .then, it tries to connect to undefined, which is the value function returned.

So, essentially what you're doing there is:

function getText() {
fetch('test.txt')
.then(function(res){
const promise = res.text();
return promise;
})
.then(function(data) {
console.log(data);
document.getElementById('output').innerHTML = data;
})
.catch(function(err){
console.log(err);
});
}


Related Topics



Leave a reply



Submit