javascript promise not passing all arguments (using Q)
Solution 1
Q promises can be resolve
d with only one argument - a promise stands for one single value, not for a collection of them. Put them in an array explicitly if you need multiple values. For the multiple-parameter-callbacks, you can use .spread()
.
Solution 2
Synchronous functions return only one value, same way asynchronous should resolve with one.
It's a bad practice to create async functions that resolve with many values. If you want to pass many values, return them in array or dict object, same as you would do if given function would be synchronous.
Nick
Well-rounded developer proficient in web (React) and mobile (React Native). Currently exploring the exciting world of Kubernetes.
Updated on June 18, 2022Comments
-
Nick almost 2 years
I am having trouble passing all arguments. My promise callback only receives one instead of three:
var asyncFunction= function(resolve) { setTimeout(function() { resolve("Some string that is passed", "and another", "third"); }, 1000); }; var promiseFunction = function () { var deferred = Q.defer(); asyncFunction(deferred.resolve); return deferred.promise; }; promiseFunction().then(function() { // Only one argument is passed here instead of 3 // { '0': 'Some string that is passed' } console.log(arguments); });
Any idea what I am doing wrong?
-
Nick almost 11 yearshow is that possible? There are thousands of libraries with async functions out there that return multiple arguments? Can't they be used then?
-
Bergi almost 11 yearsOnly with a wrapper it seems. Do you have a particular one in mind?
-
Tomalak almost 11 years@Nick The whole library is centered around the single value approach. Look at the source and try to figure out what changes would be needed to support multiple values. You'll be surprised how complex this gets while returning little or no real value. Use an array, as Bergi suggests.
-
Bergi almost 11 years@Tomalak: I'd say there's a lot of value (my own promise implementation allows it) and passing around
arguments
objects can simplify the code. Of course,Q
was built with a different paradigm from scratch and changing it would be complex now. -
Tomalak almost 11 years@Bergi Hm... If I can use an array to collect multiple values easily and pass them as one object, where is the benefit in allowing multiple parameters in the promise implementation?
-
Bergi almost 11 years@Tomalak: You can write more concise callback functions, without accessing properties/indices on the value. Think of the arrays as tuples, not as lists. The
$.ajax
promises would be a good example. -
Tomalak almost 11 years@Bergi Point taken. You'd have to pass around an object instead of an array to get the benefit of multiple "named arguments" in callback functions with Q. Agreed, that's a slight inconvenience.
-
ForbesLindesay almost 11 yearsThe reason promises only resolve with one value is that they parallel synchronous code. Q can't change it's behavior because, unlike broken libraries that support multiple values, it complies with the Promises/A+ specification
-
Bergi almost 11 years@ForbesLindesay: Actually I don't see A+ forbidding multiple values - I guess we'll have to discuss that at some time, I'll open an issue. And even synchronous code can return multiple values - while currently not allowed in JavaScript (destructuring assignments might give a syntax for that) it is a feature in other languages.
-
ForbesLindesay almost 11 yearsSynchronous JavaScript code does not return multiple values. Destructuring assignment is a syntax extension to make it easier to work with functions that return an array of values or an object map of values. That's just like
.spread
is a helper to make it easier to work with functions that return promises for arrays. -
Matt over 10 yearsPlenty of libraries using callbacks pass back multiple arguments; I don't consider this bad practice. Promises/Futures supporting multiple values also seems like a logical step. I think this should be explored, as does this mailing list entry.
-
Mariusz Nowak over 10 yearsMatt, initially in library I maintain I experimented with allowance of multiple values for resolution, but I quickly rejected that idea. I don't remember now the exact issues, but I believe there were cases when I needed to deal with resolved value as one object, and it was weird (and not on par with sync functions) to always deal with an array or arguments object. Decision is already coined and proven to be right in practice. The post you've linked as you see was quickly put down. I don't remember such idea being seriously considered.
-
Matt over 10 yearsI only care because I'm writing a promises library (for fun and learning) and multiple resolving arguments feels like such a natural solution to me. If the community has settled on a single value, so be I suppose. Thanks for the follow-up.
-
AdrianCooney over 10 years@Matt, couldn't agree more. Promises solve the problem of nasty callback nesting yet callbacks still allow for more than one argument passed. It feels quite ridiculous that I can't pass more than one argument to
.resolve
, instead I have to pack it up into an array and unpack it in the callback leading to a mess. Wasn't that what promises was avoiding in the first place, a mess? -
RadleyMith over 9 yearsjust pass an array or an object with the resolve and you'll be good