I am having trouble interpreting what the Promises/A+ spec meant by this...
https://promisesaplus.com/#point-23
If you have a promise and call .then with one argument, does that mean that the single argument will be called regardless of success or failure?
I feel like it could go either way with interpreting this. I guess the library I would be most concerned with is Q.
The first argument to a .then() handler, whether it is the only argument or not, is always the fulfilled handler and is only called if the promise is fulfilled. That first argument is not treated differently if there is or is not a second argument passed.
So to anyone who is unsure, I made a test script that you can run in your node REPL. The definitive answer is that no it will not call the success with an err attachment.
var Q = require('q');
//call with whether or not the promise will resolve
function aPromise (bool) {
var def = Q.defer();
if (!bool) {
def.reject("oooo0o0o00o0 rejected");
}
def.resolve('winner winner chicken dinner');
return def.promise
}
var whatGonnaBe = aPromise(false)
//The Example
whatGonnaBe
.then(function (response) {
console.log('1')
console.log(JSON.stringify(response) + '1');
})
.then(function (response) {
console.log('2')
console.log(JSON.stringify(response) + '2');
},
function (response) {
console.log('3')
console.log(JSON.stringify(response) + '3');
})
No, the first argument is always the "success" or "resolved" argument. The second argument is always the failure argument, and you can omit it when chaining promises together and have a single "fail" argument to handle all fails. This code is just conceptual:
promise1.then(function() {
return promise2;
}).then(function() {
return promise3;
}).then(function() {
/* everything succeeded, move forward */
}, function() {
/* catch any failure by any of the promises */
});
Related
As I understand it, resolve and reject are specified in the callback provided to the promise constructor and invoked within the callback. But resolve and reject (I think) always do the same thing, so why do they even have to be specified?
EDIT: I should clarify: I do not think that resolve does the same thing as reject; I mean resolve seems to always resolve and reject always reject -- is there a way to pass in a function instead of resolve that does something else?
EDIT: To further clarify as I did in a comment below: if a Promise constructor takes a function which in turn takes resolve and reject and these are always to be called in the function, why must resolve and reject be specified as arguments at all?
Final Edit: I tried with foo instead of resolve and it still worked. How can that be? I did not define foo at all?? I probably am not understanding something about javascript beyond promises. code snippet where i changed resolve to foo
When you create a JS Promise, you expect some task to happen asynchronously. It is possible, that this task can succeed or fail. The success and failure are defined based on what the task is.
When you create a new Promise, you as the creator must specify what to do when the task is successful or is a failure. To communicate the same to the consumer of the promise resolve/reject come handy.
So when the consumer uses a then to check the output of the promise. what ever is returned by resolve is given to the consumer.
When the consumer uses a catch to check the output of the promise. whatever is returned by the reject is given to the consumer.
import {Promise} from 'es6-promise'
const foo = true;
const bar = new Promise((resolve, reject) => {
if (foo) {
resolve(4);
} else {
reject(2);
}
})
bar.then((value) => console.log(value)).catch((value) => console.log(value));
you can run the above sample by changing the value of foo to true/false and see for yourself what the output is.
I assume you are referring to the then() function which takes two callbacks, one when the promise is resolved and one when it is resolved. The pattern often looks like this:
myPromise.then(result => {
// do something here
},
error => {
}
);
If the promise is resolved everything went as expected and the first callback should proceed as normal. If the promise is rejected the second callback should perform error handling, possibly displaying an appropriate message to the user. These never do the same thing.
If you have logic that should always occur, whether there is an error or not, you should chain another call to then():
myPromise.then(result => {
// do something here
},
error => {
// do something here
}
).then(result => {
// do something here
}
);
This is conceptually the same as try...catch...finally from many programming languages.
Resolve and reject do not "do the same thing".
When you resolve a promise you are saying "this is the successful response of this promise".
When you reject a promise you are saying "this promise failed because...".
For example:
Imagine in the following examples accountApiRequest() actually does an API request to fetch an account. If there is no account it will most likely return null or throw an exception.
When a promise is successful you will resolve it. When a promise is not successful it will be rejected.
Successful promise
function accountApiRequest() {
return {
id: 1234,
username: 'Jim',
}
}
function getAccount() {
return new Promise(function(resolve, reject) {
account = accountApiRequest()
if (!account) {
return reject('Unable to fetch account')
}
return resolve(account)
});
}
getAccount().then(console.log).catch(console.log)
Failed promise
function accountApiRequest() {
return null
}
function getAccount() {
return new Promise(function(resolve, reject) {
account = accountApiRequest()
if (!account) {
return reject('Unable to fetch account')
}
return resolve(account)
});
}
getAccount().then(console.log).catch(console.log)
In the Promise constructor we have a callback which takes the resolve and reject methods as its arguments. After a Promise is created using the constructor a Promise can have three states:
Pending
Resolved
Rejected
When a promise is resolved then the callback which is passed in the then() method is called. If the promise is rejected the callback which is passed in the catch() method is called. For example:
const prom = new Promise((resolve, reject) => {
setTimeout(() => {
if(Math.random() > 0.5) {
resolve('resolved');
} else {
reject('rejected');
}
}
, 2000)
});
prom.then((val) => console.log('succes: ' + val))
.catch((val) => console.log('fail: ' + val))
In our example the resolve or reject is called in a setTimeout, therefore the status of the promise is the first 2 seconds pending. After the setTimeout is expired the Promise is either resolved or rejected based on the value of Math.random(). Then either the then or the catch callback is executed to handle the result of the promise.
When the promise is rejected the callback passed in the catch method is called
When the promise is resolved the callback passed in the then method is called
I had the same question when I read about Promises. And I came to understanding that you don't need to define resolve and reject functions by yourself (they will be ignored and standard resolve/reject functions will be called anyway): I think of them as special functions which let you indicate whether to resolve or reject the promise by calling one of them; and what value to return in each case by passing arguments to these functions. It doesn't matter how you name them in promise constructor - first argument is resolve function and the second - reject.
I have spent a ton of time trying to figure this out. Unfortunately, for anyone well versed with JS syntax, won't really understand the question...
For me, it was clear, after unraveling the concise JS syntactic sugar:
function promise_executor(resolve_callback_provided_by_promise_instance, reject_callback_provided_by_promise_instance) {
if (<some_condition>) {
// success
var response='bla';
resolve_callback_provided_by_promise_instance(response);
} else {
// fail
var error=new Error('failed');
reject_callback_provided_by_promise_instance(error);
}
}
var promise_instance = new Promise(promise_executor);
So the reject and resolve are just random names for callbacks that the promise instance will call.
They have proper interfaces, like both will take 1 param of type object. That param will be passed to either the Promise.then() or the Promise.catch().
resolve
reject
Then, when you use them, it is like this:
function success_callback(param_from_resolve) {
console.log('success() ', param_from_resolve);
}
function fail_callback(param_from_reject) {
console.log('fail(): ', param_from_reject);
}
promise_instance
.then(success_callback) // this will be the var 'resolve' from above
.catch(fail_callback); // this will be the var 'error' from above
The whole code flow is like this:
<at some point, your promise_executor() code is called with 2 functions, as parameters>
// obviously, the promise_executor() function has its own name in the Promise object
promise_executor(Promise.reject, Promise.resolve);
<promise_executor() will -hopefully- call either the resolve or the reject callback, which will in turn trigger either the callback of then() or catch()>
<say we have then()>
<the Promise code will take the response param from resolve_callback_provided_by_promise_instance(response) and give it to the callback from then()>
param_from_resolve(response)
It will go down something like this (THIS IS NOT what actually happens, as in reality, the micro-queue, the eventloop, etc. gets involved - this is a linearized version of the gist of what is happening):
What you see:
var promise = new Promise(promise_executor);
What is executed:
function Promise.constructor(exec_callback_fnc) {
var this = object();
this.exec_callback_fnc = exec_callback_fnc; // this is "promise_executor"
return this;
}
What you see:
// at some point in "this.exec_callback_fnc":
resolve_callback_provided_by_promise_instance(response)
What is executed:
function promise_instance.resolve(param) {
this.param_from_resolve = param;
promise_instance.resolved = true;
}
What you see:
promise_instance
.then(success_callback)
What is executed:
promise_instance.exec_callback_fnc(promise_instance.resolve, promise_instance.reject);
if (promise_instance.resolved) {
function promise_instance.then(callback_fnc) {
callback_fnc(this.param_from_resolve); // this is "success_callback"
}
}
Finally, let's see, how the syntax makes this whole thing more concise:
function promise_executor(resolve_callback_provided_by_promise_instance,
reject_callback_provided_by_promise_instance) {
if (<some_condition>) {
// success
var response='bla';
resolve_callback_provided_by_promise_instance(response);
} else {
// fail
var error=new Error('failed');
reject_callback_provided_by_promise_instance(error);
}
}
var promise_instance = new Promise(promise_executor);
function success_callback(param_from_resolve) {
console.log('success() ', param_from_resolve);
}
function fail_callback(param_from_reject) {
console.log('fail(): ', param_from_reject);
}
promise_instance
.then(success_callback)
.catch(fail_callback);
Will become:
new Promise((resolve_callback_provided_by_promise_instance,
reject_callback_provided_by_promise_instance) => {
if (<some_condition>) {
// success
var response='bla';
resolve_callback_provided_by_promise_instance(response);
} else {
// fail
var error=new Error('failed');
reject_callback_provided_by_promise_instance(error);
}})
// "response" -> "param_from_resolve"
.then((param_from_resolve) => { console.log('success() ', param_from_resolve); })
// "error" -> "param_from_reject"
.catch((param_from_reject) => { console.log('fail(): ', param_from_reject); });
I'm using the popular node library, got, to make simple GET requests to a JSON API.
I have a function that abstracts the request, like so:
function performRequest(url) {
got(url, {
json: true
}).then(function (response) {
return formatResponse(response.body);
}).catch(function (error) {
console.log(error.response.body);
});
}
formatResponse is a simple synchronous method that modifies the JSON returned from the API.
I would like to be able to call performRequest from another function and then use the return value (once resolved). Currently, as performRequest is not recognized as an async method, my code is calling it and then proceeding immediately.
function myBigFunction() {
var url = composeUrl();
var res = performRequest(url);
doMoreStuffWithResponse(res);
}
I know that I need to utilize a Promise, however, I'm always unclear as to how to use a Promise in conjunction with a built-in library function that is already using a Promise (like in this case).
I'm also completely open to the possibility that I'm going about this all wrong. In that case, I would appreciate some redirection.
Thank you for your time.
Understand what a Promise is. Its a value, you can treat it as such. In order to "read" the value, you pass a function to the Promise's then method. You don't need myBigFunction. Anything you want to run after the Promise resolves just needs to be passed to then:
var req = performRequest(composeURL());
req.then(doStuffWithResponse);
Now, I don't particularly care for this way although I do it fairly often. I prefer to have functions that take promises and invoke their then method:
var takesAPromise = function(p) {
return p.then(/* does stuff */);
};
Note that it returns the Promise of the completed task. But what I like even better is this ES6 one-liner:
let wrap = f => p => p.then(val => f.call(null, val));
Now you can wrap arbitrary functions to take Promises as input and return them as output. If Promises were a monad, this would be their bind function. Making it work seamlessly with functions of arbitrary arity is left as an exercise to the reader.
You'll always want to return a promise from your functions:
function performRequest(url) {
return got(url, {
//^^^^^^
json: true
}).then(function(response) {
return formatResponse(response.body);
}, function(error) {
throw new Error(error.response.body);
});
}
With this, you can wait for the result in your big functions using another then:
function myBigFunction() {
var url = composeUrl();
var promise = performRequest(url);
return promise.then(function(res) {
return doMoreStuffWithResponse(res);
});
}
or in short
function myBigFunction() {
return performRequest(composeUrl()).then(doMoreStuffWithResponse);
}
so that you can call it like
myBigFunction().catch(function(error) {
console.log(error.message);
});
I just implemented my first function that returns a promise based on another promise in AngularJS, and it worked. But before I decided to just do it, I spent 2 hours reading and trying to understand the concepts behind promises. I thought if I could write a simple piece of code that simulated how promises worked, I would then be able to conceptually understand it instead of being able to use it without really knowing how it works. I couldn't write that code.
So, could someone please illustrate in vanilla JavaScript how promises work?
A promise is basically an object with two methods. One method is for defining what to do, and one is for telling when to do it. It has to be possible to call the two methods in any order, so the object needs to keep track of which one has been called:
var promise = {
isDone: false,
doneHandler: null,
done: function(f) {
if (this.isDone) {
f();
} else {
this.doneHandler = f;
}
},
callDone: function() {
if (this.doneHandler != null) {
this.doneHandler();
} else {
this.isDone = true;
}
}
};
You can define the action first, then trigger it:
promise.done(function(){ alert('done'); });
promise.callDone();
You can trigger the action first, then define it:
promise.callDone();
promise.done(function(){ alert('done'); });
Demo: http://jsfiddle.net/EvN9P/
When you use a promise in an asynchronous function, the function creates the empty promise, keeps a reference to it, and also returns the reference. The code that handles the asynchronous response will trigger the action in the promise, and the code calling the asynchronous function will define the action.
As either of those can happen in any order, the code calling the asynchronous function can hang on to the promise and define the action any time it wants.
For the simplicity to understand about the promises in Javascript.
You can refer below example. Just copy paste in a new php/html file and run.
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
function test(n){
alert('input:'+n);
var promise = new Promise(function(fulfill, reject) {
/*put your condition here */
if(n) {
fulfill("Inside If! match found");
}
else {
reject(Error("It broke"));
}
});
promise.then(function(result) {
alert(result); // "Inside If! match found"
}, function(err) {
alert(err); // Error: "It broke"
});
}
</script>
</head>
<body>
<input type="button" onclick="test(1);" value="Test"/>
</body>
</html>
Click on Test button,
It will create new promise,
if condition will be true it fulfill the response,
after that promise.then called and based on the fulfill it will print the result.
In case of reject promise.then returns the error message.
Probably the simplest example of promises usage looks like that:
var method1 = (addings = '') => {
return new Promise(resolve => {
console.log('method1' + addings)
resolve(addings + '_adding1');
});
}
var method2 = (addings = '') => {
return new Promise(resolve => {
console.log('method2' + addings)
resolve(addings + '_adding2');
});
}
method1().then(method2).then(method1).then(method2);
// result:
// method1
// method2_adding1
// method1_adding1_adding2
// method2_adding1_adding2_adding1
That's basic of basics. Having it, you can experiment with rejects:
var method1 = (addings = '*') => {
return new Promise((resolve, reject) => {
console.log('method1' + addings)
resolve(addings + '_adding1');
});
}
var method2 = (addings = '*') => {
return new Promise((resolve, reject) => {
console.log('method2' + addings)
reject();
});
}
var errorMethod = () => {
console.log('errorMethod')
}
method1()
.then(method2, errorMethod)
.then(method1, errorMethod)
.then(method2, errorMethod)
.then(method1, errorMethod)
.then(method2, errorMethod);
// result:
// method1*
// method2*_adding1
// errorMethod
// method2*
// errorMethod
// method2*
As we can see, in case of failure error function is fired (which is always the second argument of then) and then next function in chain is fired with no given argument.
For advanced knowledge I invite you here.
please check this simple promise code. this will help you to better understand of promise functionality.
A promise is an object that may produce a single value some time in the future: either a resolved value, or a reason that it’s not resolved. A promise may be in one of 3 possible states: fulfilled, rejected, or pending. Promise users can attach callbacks to handle the fulfilled value or the reason for rejection.
let myPromise = new Promise((resolve, reject)=>{
if(2==2){
resolve("resolved")
}else{
reject("rejected")
}
});
myPromise.then((message)=>{
document.write(`the promise is ${message}`)
}).catch((message)=>{
document.write(`the promise is ${message}`)
})
check this out
I have some code that handles Angular promises like this
somethingThatReturnsAPromise
.then(function (data) {
// handle success
})
.catch(function (error) {
// handle error
})
.finally(function () {
// always do this
});
I understand this syntax is deprecated now, and this code should be replaced with
somethingThatReturnsAPromise.then(
function (data) {
// handle success
},
function (error) {
// handle error
}
);
But where should I put the code that was previously in finally when using this new syntax, i.e. code that is executed both when the promise is resolved (successful) and rejected (fails)?
If you want to go with then either way, you can provide a handler for both success and error promise handlers:
function always() {
// Do whatever either it fails or succeeds
}
somethingThatReturnsAPromise.then(always, always).then(function(data) {
}, function(error) {
});
1st: I didn't find anything about any (Promise-related) method being deprecated in the official docs.
2nd: finally is way more complicated then a then(cb, cb), since it doesn't catch Errors, and doesn't propagate the results of your callback, but if you return a promise, it waits for this promise to resolve until it continues propagating the current value.
Sth like this:
function _finally(promise, callback) {
var handleValue = isError => value => $q((resolve, reject) => {
//call your callback
//if this throws, propagate the Error
var w = typeof callback === "function" && callback();
//prepare to push the current value/error
var fn = isError?
() => reject(value):
() => resolve(value);
//check wether your callback has returned sth. Promise-like
if(w && typeof w.then === "function"){
//then we'll wait for this to resolve,
//before we continue propagating the current value/error
w.then(fn, fn);
}else{
//otherwise propagate the current value/error emmediately
fn();
}
});
return $q.resolve(promise).then(
handleValue(false),
handleValue(true)
);
}
I wrote this code only to give you an implession what finally does. Angular's implementation is smoother, so stick with that.
I don't see any reason to think that catch or finally are deprecated or will ever be.
I'm doing a series of sequential AJAX calls in jQuery, using the usual method of chaining with Deferred. The first call returns a list of values and the subsequent calls are made with those returned list entries. After the first call that returns the list, the subsequent calls may be done in any order, but they must be done one at a time. So this is what I use:
$.when(callWebService()).then(
function (data) {
var looper = $.Deferred().resolve(),
myList = JSON.parse(data);
for (var i in myList) {
(function (i) {
looper = looper.then(function () { // Success
return callWebService();
},
function (jqXHR, textStatus, errorThrown) { // Failure
if (checkIfContinuable(errorThrown) == true)
continueChain();
else
failWithTerribleError();
});
})(i);
}
});
It turns out that the subsequent calls may fail at times, but I still want to do the remainder of the calls. In my listing, that's what this little bit of inventive pseudo code is meant to do:
if (checkIfContinuable(errorThrown) == true)
continueChain();
else
failWithTerribleError();
How on earth do I implement continueChain though? It appears as though a failure on any deferred will cause the rest of the chain to also fail. Instead, I'd like to log the error and continue with the rest of the list.
With Promises/A+ this is as easy as
promise.then(…, function(err) {
if (checkIfContinuable(err))
return valueToConinueWith;
else
throw new TerribleError(err);
})
Unfortunately, jQuery is still not Promises/A+ compliant, and forwards the old value (result or error) - unless you return a jQuery Deferred from the callback. This works just the same way as rejecting from the success handler:
jDeferred.then(…, function(err) {
if (checkIfContinuable(err))
return $.Deferred().resolve(valueToConinueWith);
else
return $.Deferred().reject(new TerribleError(err));
})
Recovering from an error in a jQuery promise chain is more verbose than with Promises/A+ implementations, which naturally catch errors in a .catch's or a .then's error handler. You have to throw/rethrow in order to propagate the error state.
jQuery works the other way round. A .then's error handler (.catch doesn't exist) will naturally propagate the error state. To emulate "catch", you have to return a resolved promise, and the chain will progress down its success path.
Starting with an array of items on which you want to base a series of async calls, it's convenient to use Array.prototype.reduce().
function getWebServiceResults() {
return callWebService().then(function(data) {
var myList;
// This is genuine Javascript try/catch, in case JSON.parse() throws.
try {
myList = JSON.parse(data);
}
catch (error) {
return $.Deferred().reject(error).promise();//must return a promise because that's what the caller expects, whatever happens.
}
//Now use `myList.reduce()` to build a promise chain from the array `myList` and the items it contains.
var promise = myList.reduce(function(promise, item) {
return promise.then(function(arr) {
return callWebService(item).then(function(result) {
arr.push(result);
return arr;
}, function(jqXHR, textStatus, errorThrown) {
if(checkIfContinuable(errorThrown)) {
return $.when(arr); // return a resolved jQuery promise to put promise chain back on the success path.
} else {
return new Error(textStatus);//Although the error state will be naturally propagated, it's generally better to pass on a single js Error object rather than the three-part jqXHR, textStatus, errorThrown set.
}
});
});
}, $.when([])) // starter promise for the reduction, resolved with an empty array
// At this point, `promise` is a promise of an array of results.
return promise.then(null, failWithTerribleError);
});
}
Notes:
An overall function wrapper is assumed, function getWebServiceResults() {...}.
callWebService() is assumed to accept item - ie the contents of each element of myList.
To do its job, checkIfContinuable() must accept at least one argument. It is assumed to accept errorThrown but might equally accept jqXHR or textStatus.