javascript promise not passing all arguments (using Q)

11,518

Solution 1

Q promises can be resolved 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.

Share:
11,518
Nick
Author by

Nick

Well-rounded developer proficient in web (React) and mobile (React Native). Currently exploring the exciting world of Kubernetes.

Updated on June 18, 2022

Comments

  • Nick
    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
    Nick almost 11 years
    how is that possible? There are thousands of libraries with async functions out there that return multiple arguments? Can't they be used then?
  • Bergi
    Bergi almost 11 years
    Only with a wrapper it seems. Do you have a particular one in mind?
  • Tomalak
    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
    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
    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
    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
    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
    ForbesLindesay almost 11 years
    The 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
    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
    ForbesLindesay almost 11 years
    Synchronous 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
    Matt over 10 years
    Plenty 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
    Mariusz Nowak over 10 years
    Matt, 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
    Matt over 10 years
    I 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
    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
    RadleyMith over 9 years
    just pass an array or an object with the resolve and you'll be good