简体   繁体   中英

Why does this resolved Q promise responds to valueOf() with a promise?

I have an object whose value comes from an AJAX request. I'm converting it to a promise and am encountering some behaviour with promises that I don't expect. I have an example here that exhibits the same behaviour, but I'm substituting Q.all() for my AJAX request.

(Thing = function(){
  var promise;
  var refresh = function() {
    promise = Q.all(["a", "b"]);
  };

  var fetch = function(i) {
    return promise.then(function(promiseVal){
      return promiseVal[i];
    });
  };

  refresh();

  return {
    "fetch": fetch,
    "refresh": refresh,
    "promise": promise
  };

}());

Thing is executed on load and runs "refresh" to populate itself initially. The point of the "fetch" function is that my async request (Q.all in this case) returns a promise for an array, but what I really want is a promise for elements in the array (eg a promise for "a" or a promise for "b"). So I'm expecting Thing.fetch(1) to return a promise for "b".

Thing.fetch(1) does return a promise, but if I do Thing.fetch(1).valueOf() it returns a promise, not "b" as I was expecting. If I do:

Thing.fetch(1).then(function(foo){
  console.log(foo);
});

it will print "b" on the console.

If I do Thing.promise.valueOf() it returns the array, so the promise is resolved when I call "fetch".

So my question is why doesn't valueOf() return a value when I call it on the promise returned by "fetch"?

It seems your promise is not resolved yet.

It's not well documented, but scattered over the wiki pages I found:

The valueOf call returns the promise itself by default.

The valueOf method is useful for providing information about the promise in the same turn of the event loop. For example, resolved promises return their resolution value and rejections return an object that is recognized by isRejected.

If the promise is fulfilled, promise.valueOf() returns the fulfilled value. If the promise is or has forwarded to a deferred promise, it returns most recently deferred promise. For rejected promises, promise.valueOf() returns a sentinel object with {rejectedPromise: true, reason: {}}

When you're doing Thing.fetch(1).then(console.log); it will of course print "b" on the console - that's the resolve value which is passed to the callback. But notice that it will invoke the log function in the future!

Because the value of the promise is an array. The value of the function passed to "then" will be some value. Your fetch method is not really returning a promise, it is resolving a promise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM