Promises, pass additional parameters to then chain
Solution 1
You can use Function.prototype.bind
to create a new function with a value passed to its first argument, like this
P.then(doWork.bind(null, 'text'))
and you can change doWork
to,
function doWork(text, data) {
consoleToLog(data);
}
Now, text
will be actually 'text'
in doWork
and data
will be the value resolved by the Promise.
Note: Please make sure that you attach a rejection handler to your promise chain.
Working program: Live copy on Babel's REPL
function doWork(text, data) {
console.log(text + data + text);
}
new Promise(function (resolve, reject) {
var a = 5;
if (a) {
setTimeout(function () {
resolve(a);
}, 3000);
} else {
reject(a);
}
})
.then(doWork.bind(null, 'text'))
.catch(console.error);
Solution 2
Perhaps the most straightforward answer is:
P.then(function(data) { return doWork('text', data); });
Or, since this is tagged ecmascript-6
, using arrow functions:
P.then(data => doWork('text', data));
I find this most readable, and not too much to write.
Solution 3
Use currying.
var P = new Promise(function (resolve, reject) {
var a = 5;
if (a) {
setTimeout(function(){
resolve(a);
}, 3000);
} else {
reject(a);
}
});
var curriedDoWork = function(text) {
return function(data) {
console.log(data + text);
}
};
P.then(curriedDoWork('text'))
.catch(
//some error handling
);
Solution 4
The new answer to this question is to use arrow functions (which automatically bind the this
and are much more readable). Google for links such as:
https://2ality.com/2016/02/arrow-functions-vs-bind.html
You can set the text like:
this.text = 'text';
P.then(data => doWork(data));
Note: this.text
inside doWork
will evaluate to 'text'.
This is suggested by jib above and that (or this!) should be the accepted answer now.
Related videos on Youtube
user3110667
Updated on July 08, 2022Comments
-
user3110667 almost 2 years
A promise, just for example:
var P = new Promise(function (resolve, reject) { var a = 5; if (a) { setTimeout(function(){ resolve(a); }, 3000); } else { reject(a); } });
After we call the
.then()
method on the promise:P.then(doWork('text'));
Then
doWork
function looks like this:function doWork(data) { return function(text) { // sample function to console log consoleToLog(data); consoleToLog(b); } }
How can I avoid returning an inner function in doWork, to get access to data from the promise and text parameters? Are there any tricks to avoiding the inner function?
-
Admin almost 8 yearsWhy would anyone intentionally renounce currying? In order to use the hideous
bind
method? - which is also extremely slow. -
Roland over 6 years@ftor I don't understand you, can you please provide some code for clarification?
-
-
user3110667 over 8 yearsthanks, that helps, earlier i try doWork.call(this, 'text'), but data was replaced by 'text'
-
sdgluck over 8 years
call
invokes a function in-place,bind
creates a new function, however both accept an execution context as their first argument. -
Flame about 6 yearsb careful with this, if you create
curriedDoWork
into a promise by doingreturn new Promise()
on the first line of this function, the promise is executed as soon as you callcurriedDoWork()
(like you do in..then(curriedDoWork('text'))
-
germain almost 6 years@Flame: short answer, for your convenience you can wrap the promise into a function, if you like to do so.
-
germain almost 6 years@yks, you could have indicated this syntax which is quite interesting const curriedWork = text => data => console.log(data + text)
-
yks almost 6 years@germain ah yes i have seen this form before, gotta love functional programming. However i experience arrow functions break in some browser, so i tend to avoid it now.
-
germain almost 6 years@yks, only Internet Explorer doesn't support it and will never, because of Edge, Internet Explorer last build was December 9th 2015. Let's move on ~
-
Reahreic about 3 yearsIn your es6 example & 'classes' how would I go about replacing "text" with a reference to an item in an array I was iterating through when creating the promise. EG:
fetch(request).then(data => this.AssetRetrieved(jData.parms[i].Value, data));
-
jib about 3 years@Reahreic That sounds like a variation of the JS closures in a loop problem. Is this answer helpful? If not, please consider asking a new question with more details.