Coder Social home page Coder Social logo

rsvp.js's Introduction

RSVP.js Build Status Inline docs

RSVP.js provides simple tools for organizing asynchronous code.

Specifically, it is a tiny implementation of Promises/A+.

It works in node and the browser (IE9+, all the popular evergreen ones).

downloads

CDN

<script src="https://cdn.jsdelivr.net/npm/rsvp@4/dist/rsvp.min.js"></script>

Promises

Although RSVP is ES6 compliant, it does bring along some extra toys. If you would prefer a strict ES6 subset, I would suggest checking out our sibling project https://github.com/stefanpenner/es6-promise, It is RSVP but stripped down to the ES6 spec features.

Node

yarn add --save rsvp
# or ...
npm install --save rsvp

RSVP.Promise is an implementation of Promises/A+ that passes the test suite.

It delivers all promises asynchronously, even if the value is already available, to help you write consistent code that doesn't change if the underlying data provider changes from synchronous to asynchronous.

It is compatible with TaskJS, a library by Dave Herman of Mozilla that uses ES6 generators to allow you to write synchronous code with promises. It currently works in Firefox, and will work in any browser that adds support for ES6 generators. See the section below on TaskJS for more information.

Basic Usage

var RSVP = require('rsvp');

var promise = new RSVP.Promise(function(resolve, reject) {
  // succeed
  resolve(value);
  // or reject
  reject(error);
});

promise.then(function(value) {
  // success
}).catch(function(error) {
  // failure
});

Once a promise has been resolved or rejected, it cannot be resolved or rejected again.

Here is an example of a simple XHR2 wrapper written using RSVP.js:

var getJSON = function(url) {
  var promise = new RSVP.Promise(function(resolve, reject){
    var client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

    function handler() {
      if (this.readyState === this.DONE) {
        if (this.status === 200) { resolve(this.response); }
        else { reject(this); }
      }
    };
  });

  return promise;
};

getJSON("/posts.json").then(function(json) {
  // continue
}).catch(function(error) {
  // handle errors
});

Chaining

One of the really awesome features of Promises/A+ promises are that they can be chained together. In other words, the return value of the first resolve handler will be passed to the second resolve handler.

If you return a regular value, it will be passed, as is, to the next handler.

getJSON("/posts.json").then(function(json) {
  return json.post;
}).then(function(post) {
  // proceed
});

The really awesome part comes when you return a promise from the first handler:

getJSON("/post/1.json").then(function(post) {
  // save off post
  return getJSON(post.commentURL);
}).then(function(comments) {
  // proceed with access to post and comments
});

This allows you to flatten out nested callbacks, and is the main feature of promises that prevents "rightward drift" in programs with a lot of asynchronous code.

Errors also propagate:

getJSON("/posts.json").then(function(posts) {

}).catch(function(error) {
  // since no rejection handler was passed to the
  // first `.then`, the error propagates.
});

You can use this to emulate try/catch logic in synchronous code. Simply chain as many resolve callbacks as you want, and add a failure handler at the end to catch errors.

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // proceed with access to posts and comments
}).catch(function(error) {
  // handle errors in either of the two requests
});

Error Handling

There are times when dealing with promises that it seems like any errors are being 'swallowed', and not properly raised. This makes it extremely difficult to track down where a given issue is coming from. Thankfully, RSVP has a solution for this problem built in.

You can register functions to be called when an uncaught error occurs within your promises. These callback functions can be anything, but a common practice is to call console.assert to dump the error to the console.

RSVP.on('error', function(reason) {
  console.assert(false, reason);
});

RSVP allows Promises to be labeled: Promise.resolve(value, 'I AM A LABEL') If provided, this label is passed as the second argument to RSVP.on('error')

RSVP.on('error', function(reason, label) {
  if (label) {
    console.error(label);
  }

  console.assert(false, reason);
});

NOTE: promises do allow for errors to be handled asynchronously, so this callback may result in false positives.

Finally

finally will be invoked regardless of the promise's fate, just as native try/catch/finally behaves.

findAuthor().catch(function(reason){
  return findOtherAuthor();
}).finally(function(){
  // author was either found, or not
});

Arrays of promises

Sometimes you might want to work with many promises at once. If you pass an array of promises to the all() method it will return a new promise that will be fulfilled when all of the promises in the array have been fulfilled; or rejected immediately if any promise in the array is rejected.

var promises = [2, 3, 5, 7, 11, 13].map(function(id){
  return getJSON("/post/" + id + ".json");
});

RSVP.all(promises).then(function(posts) {
  // posts contains an array of results for the given promises
}).catch(function(reason){
  // if any of the promises fails.
});

Hash of promises

If you need to reference many promises at once (like all()), but would like to avoid encoding the actual promise order you can use hash(). If you pass an object literal (where the values are promises) to the hash() method it will return a new promise that will be fulfilled when all of the promises have been fulfilled; or rejected immediately if any promise is rejected.

The key difference to the all() function is that both the fulfillment value and the argument to the hash() function are object literals. This allows you to simply reference the results directly off the returned object without having to remember the initial order like you would with all().

var promises = {
  posts: getJSON("/posts.json"),
  users: getJSON("/users.json")
};

RSVP.hash(promises).then(function(results) {
  console.log(results.users) // print the users.json results
  console.log(results.posts) // print the posts.json results
});

All settled and hash settled

Sometimes you want to work with several promises at once, but instead of rejecting immediately if any promise is rejected, as with all() or hash(), you want to be able to inspect the results of all your promises, whether they fulfill or reject. For this purpose, you can use allSettled() and hashSettled(). These work exactly like all() and hash(), except that they fulfill with an array or hash (respectively) of the constituent promises' result states. Each state object will either indicate fulfillment or rejection, and provide the corresponding value or reason. The states will take one of the following formats:

{ state: 'fulfilled', value: value }
  or
{ state: 'rejected', reason: reason }

Deferred

The RSVP.Promise constructor is generally a better, less error-prone choice than RSVP.defer(). Promises are recommended unless the specific properties of deferred are needed.

Sometimes one needs to create a deferred object, without immediately specifying how it will be resolved. These deferred objects are essentially a wrapper around a promise, whilst providing late access to the resolve() and reject() methods.

A deferred object has this form: { promise, resolve(x), reject(r) }.

var deferred = RSVP.defer();
// ...
deferred.promise // access the promise
// ...
deferred.resolve();

TaskJS

The TaskJS library makes it possible to take promises-oriented code and make it synchronous using ES6 generators.

Let's review an earlier example:

getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function(comments) {
  // proceed with access to posts and comments
}).catch(function(reason) {
  // handle errors in either of the two requests
});

Without any changes to the implementation of getJSON, you could write the following code with TaskJS:

spawn(function *() {
  try {
    var post = yield getJSON("/post/1.json");
    var comments = yield getJSON(post.commentURL);
  } catch(error) {
    // handle errors
  }
});

In the above example, function * is new syntax in ES6 for generators. Inside a generator, yield pauses the generator, returning control to the function that invoked the generator. In this case, the invoker is a special function that understands the semantics of Promises/A, and will automatically resume the generator as soon as the promise is resolved.

The cool thing here is the same promises that work with current JavaScript using .then will work seamlessly with TaskJS once a browser has implemented it!

Instrumentation

function listener (event) {
  event.guid      // guid of promise. Must be globally unique, not just within the implementation
  event.childGuid // child of child promise (for chained via `then`)
  event.eventName // one of ['created', 'chained', 'fulfilled', 'rejected']
  event.detail    // fulfillment value or rejection reason, if applicable
  event.label     // label passed to promise's constructor
  event.timeStamp // milliseconds elapsed since 1 January 1970 00:00:00 UTC up until now
  event.stack     // stack at the time of the event. (if  'instrument-with-stack' is true)
}

RSVP.configure('instrument', true | false);
// capturing the stacks is slow, so you also have to opt in
RSVP.configure('instrument-with-stack', true | false);

// events
RSVP.on('created', listener);
RSVP.on('chained', listener);
RSVP.on('fulfilled', listener);
RSVP.on('rejected', listener);

Events are only triggered when RSVP.configure('instrument') is true, although listeners can be registered at any time.

Building & Testing

Custom tasks:

  • npm test - build & test
  • npm test:node - build & test just node
  • npm test:server - build/watch & test
  • npm run build - Build
  • npm run build:production - Build production (with minified output)
  • npm start - build, watch and run interactive server at http://localhost:4200'

Releasing

Check what release-it will do by running npm run-script dry-run-release. To actually release, run node_modules/.bin/release-it.

rsvp.js's People

Contributors

amilkey avatar bekzod avatar brzpegasus avatar calvinmetcalf avatar chadhietala avatar cyril-sf avatar decasia avatar dependabot[bot] avatar domenic avatar eventualbuddha avatar fivetanley avatar jbrown avatar joliss avatar josh avatar krisselden avatar locks avatar machty avatar majorbreakfast avatar mikepmunroe avatar rondale-sc avatar rwaldron avatar rwjblue avatar sandstrom avatar stefanpenner avatar supercrabtree avatar teddyzeenny avatar tomdale avatar twokul avatar wagenet avatar wycats avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rsvp.js's Issues

Are there build instructions anywhere?

Hello, I just figured out that I had to run bundle install and bundle exec rake (and I believe update my gems beforehand) to build RSVP. Would that be good addition to the readme?

// maybe download ruby from somewhere
gem update
bundle install
bundle exec rake
npm install
npm test

or so?

RSVP.all is non-deterministic

When two promises passed to RSVP.all fail, the error returned by RSVP.all will be that of whichever promise failed first in time. This makes it non-deterministic in practice.

(My real-world use case where this is a problem: I'm compiling a bunch of files, each file represented by a promise, and waiting for all of them to complete. If any of them fail, I'd want the compilation error message to be deterministic.)

I wonder if this is worth fixing. For instance, RSVP.all could collect all errors, and return the one with the lowest index in the array.

On the other hand, there are scenarios where failing as early as possible is more desirable, for example when we have a bunch of network requests. So perhaps we need a separate function, if at all. We could still document that RSVP.all is non-deterministic.

Thoughts either way?


Here is an example illustrating the problem:

var rsvp = require('rsvp')

var promise1 = new rsvp.Promise(function (resolve, reject) {
  setTimeout(function () {
    reject('promise1')
  }, 200)
})

var promise2 = new rsvp.Promise(function (resolve, reject) {
  setTimeout(function () {
    reject('promise2')
  }, 100)
})

rsvp.all([promise1, promise2]).then(undefined, function (err) {
  // Logs "promise2", because promise2 happens to fail first.
  console.log(err)
})

Exception thrown from then callback is lost

If I throw an exception from within a then callback it gets caught in invokeCallback() and passed as an argument to reject the 'then' promise. The problem is if I don't have a 'then' on my 'then' to receive this then the exception is lost and processing has stopped and I have no indication of why.

Not really sure about best behavior here. Maybe reject the 'then' promise as existing before testing for a reject callback, If no callback then re-throw.

typeof process === 'undefined' may be insufficient

If a process Identifier has been initialized and assigned any value (except undefined) the typeof process === "undefined" condition will be a false positive.

typeof process === 'undefined' && {}.toString.call(process) === '[object process]'

Patch to follow

Is the documentation accurate?

In hailing the advantages of Promise/A+ chaining, you use the following example:

getJSON("/post/1.json").then(function(post) {
  // save off post
  return getJSON(post.commentURL);
}).then(function(comments) {
  // proceed with access to posts and comments
});;

Is the comment in the last .then clause accurate? (It is possible I don't understand what is intended by "save off post") Certainly, the code can "proceed with access to comments," but how exactly can it access the post returned in the first .then clause callback? Of course, the following accomplishes that result, but shouldn't we make this clear?

getJSON("/post/1.json").then(function(post) {
  // save off post
  return RSVP.all(post, getJSON(post.commentURL));
}).then(function(array) {
  // proceed with access to posts (array[0]) and comments (array[1])
});;

and/or

var gPost = null
getJSON("/post/1.json").then(function(post) {
  // save off post
  gPost = post
  getJSON(post.commentURL)
}).then(function(comments) {
  // proceed with access to gPost and comments
});;

Add RSVP.resolve as a better version of contemplated "wrap" or "fromDeferred" methods.

See #59, #42, and #52 for preceding ideas in this vein.

RSVP.resolve should have the signature RSVP.resolve(x), where x can be any value. If x is a thenable, it is assimilated to become an RSVP promise; if it is a non-thenable, a new promise is created fulfilled with x.

More details on the exact algorithm that should be used is found in the Promise Resolution Procecure, which will shortly become part of the Promises/A+ spec (version 1.1).

Implementing the resolution procedure will also likely help fix the failing tests introduced by #56, i.e. it should make

var promise = new RSVP.Promise(function (resolve) { resolve(thenable); });

or

var deferred = RSVP.defer();
deferred.resolve(thenable);

work correctly.

Building for node fails on master

When trying to build the latest master for node.js (version 0.10), I get the following:

$ rake
/Users/michael/.rbenv/versions/1.9.3-p385/lib/ruby/gems/1.9.1/gems/bundler-1.3.4/lib/bundler/rubygems_integration.rb:214:in `block in replace_gem': js_module_transpiler is not part of the bundle. Add it to Gemfile. (Gem::LoadError)
    from /Users/michael/.rbenv/versions/1.9.3-p385/lib/ruby/gems/1.9.1/bin/compile-modules:22:in `<main>'


/Users/michael/.rbenv/versions/1.9.3-p385/lib/ruby/gems/1.9.1/gems/bundler-1.3.4/lib/bundler/rubygems_integration.rb:214:in `block in replace_gem': js_module_transpiler is not part of the bundle. Add it to Gemfile. (Gem::LoadError)
    from /Users/michael/.rbenv/versions/1.9.3-p385/lib/ruby/gems/1.9.1/bin/compile-modules:22:in `<main>'

However, I'm a little confused because I thought that the js_module_transpiler had been replaced by the es6-module-transpiler. So I'm not sure why js_module_transpiler still needs to be present in the Gemfile.

Promises broken in Mobile Safari while tab switcher is active

I had this issue with a version of Q on a different project, but updating to the latest fixed it. Basically, resolving or rejecting a promise while the tab switcher is active prevents the promise from ever being resolved or rejected.

From the similar experience I had with Q, it appears that it has to do with nextTick. Things like setTimeout do not work while the tab switcher is active (nor apparently do browser mutation events, from what I can grok reading RSVP's source). However, the MessageChannel approach does work, even with the tab switcher active.

For an actual use case, I'm using RSVP around Facebook authentication. When a user logs in for the first time, a login dialog is presented in a new tab. When the user logs in or cancels, the dialog closes and triggers a callback where I resolve or reject the promise about the login attempt, respectively. During this time, the tab switcher is shown and the user must tap the original tab again to activate it. My implementation works in every browser I've tested, but not in Mobile Safari due to the tab switcher tick issue.

I actually attempted a workaround by returning a "fake" promise for the login attempt. It had a "then" method which would directly execute the success or failure callback rather than waiting for another tick. This worked except that the fake promise is nested inside a real promise, so it breaks there instead. I would have to fake every promise up the hierarchy for my workaround to, uh, work.

grunt-microlib grunt-es6-module-transpiler dep

Looks like git://github.com/thomasboyt/grunt-es6-module-transpiler.git doesn't exist anymore so when you clone the project for the first time, npm install fails. I had to change it to git://github.com/joefiorini/grunt-es6-module-transpiler.git.
/cc @thomasboyt

Promise state changed after notification

In the RSVP code, the promise flags are updated after the trigger :

function resolve(promise, value) {
  config.async(function() {
    promise.trigger('promise:resolved', { detail: value });
    promise.isResolved = true;
    promise.resolvedValue = value;
  });
}

function reject(promise, value) {
  config.async(function() {
    promise.trigger('promise:failed', { detail: value });
    promise.isRejected = true;
    promise.rejectedValue = value;
  });

Thus, in the following code :

var a = new Promise();
a.then(function () {
  a.then(function () {
    console.log('resolved');
  });
});

'resolved' will never printed

Multiple arguments for resolve

Is it possible to pass multiple arguments when resolving a promise? Something like this:

var Promise = require("RSVP").Promise;
var promise = new Promise();
promise.then(function() {
    console.log(arguments); //prints only "foo" now
});

promise.resolve.call(promise, "foo", "bar");

Running in node 0.6 prints:
{ '0': 'foo' }

unable to create a promise

the version in master now gives an err, when I do

var promise = new RSVP.Promise();

it throws:

"TypeError: You must pass a resolver function as the sole argument to the promise constructor"

RSVP crashes Node 0.10.x

RSVP fails pretty spectacularly under Node 0.10.x when too many promises are returned in .then callbacks. This is demonstrated in the initial commit of wizardwerdna/torture_rsvp. A proposed solution is demonstrated in the second and third commits, essentially selecting setImmediate in favor of nextTick, when both are available.

The problem arises in the use of nextTick inside of a nextTick when .then's are resolved. My respository cribbed an example from Brian 's promise-perf-tests. Many promise implementations died horrible deaths with the change, and alas, rsvp was a casualty.

Prior to 0.10.x, process.nextTick deferrals got highest priority (performed before the event loop) unless process.maxNextTick deferrals were queued, in which case, the system would give the event loop a spin before proceeding. In 0.10.x, this was changed to ASSURE that all nextTicks would be completed before the event lop was run again. Accordingly, "recursive" calls to nextTick from nextTick-scheduled functions can now run up the stack and crash the system.

FASTER PROCESS.NEXTTICK

In v0.8 (and before), the process.nextTick() function scheduled its callback using a spinner on the event loop. This usually caused the callback to be fired before any other I/O. However, it was not guaranteed.

As a result, a lot of programs (including some parts of Node's internals) began using process.nextTick as a "do later, but before any actual I/O is performed" interface. Since it usually works that way, it seemed fine.

However, under load, it's possible for a server to have a lot of I/O scheduled, to the point where the nextTick gets preempted for something else. This led to some odd errors and race conditions, which could not be fixed without changing the semantics of nextTick.

So, that's what we did. In v0.10, nextTick handlers are run right after each call from C++ into JavaScript. That means that, if your JavaScript code calls process.nextTick, then the callback will fire as soon as the code runs to completion, but before going back to the event loop. The race is over, and all is good.

However, there are programs out in the wild that use recursive calls to process.nextTick to avoid pre-empting the I/O event loop for long-running jobs. In order to avoid breaking horribly right away, Node will now print a deprecation warning, and ask you to use setImmediate for these kinds of tasks instead.

There are many other solutions, but this simple expedient seems the best bang for the buck.

I hope this is helpful.

RSVP is 'null'

I've included the rsvp-amd.js script as an AMD module dependency in the usual require way, and RSVP is 'null'... Can't figure this out for the life of me! Has anyone else experience this? My module definition is written as follows:

define([
    'lib/rsvp'
], function (RSVP) {
    // This creates an error:
    var promise = new RSVP.Promise();
    // "Uncaught TypeError: Cannot read property 'Promise' of null"
});

The file path is definitely correct, as I can see the script loaded in the network panel. Also, if I just use the normal non-AMD script, and reference the global "window.RSVP", it works as expected.

Any ideas?

Cheers

[Promises/A+] throwing falsy values in onFulfilled or onRejected

This does not work:

var promise1 = new RSVP.Promise();
promise1.fulfill();

var promise2 = promise1.then(function () {
  throw anyFalsyValue;
});

promise2.then(null, function (reason) {
  assert(reason === anyFalsyValue);
});

Also, this does not work except for anyFalsyValue is undefined:

var promise1 = new RSVP.Promise();
promise1.reject();

var promise2 = promise1.then(null, function () {
  throw anyFalsyValue;
});

promise2.then(null, function (reason) {
  assert(reason === anyFalsyValue);
});

[Promises/A+] returning pseudo-promises or already-fulfilled or already-rejected promises

Basically, the following Promises/A+ tests fail:

3.2.6.3.2: If/when `returnedPromise` is fulfilled, `promise2` must be fulfilled with the same value.
  `promise1` is fulfilled, and `returnedPromise` is:
    34) already-fulfilled
    35) a pseudo-promise
  `promise1` is rejected, and `returnedPromise` is:
    36) already-fulfilled
    37) a pseudo-promise
3.2.6.3.3: If/when `returnedPromise` is rejected, `promise2` must be rejected with the same reason.
  `promise1` is fulfilled, and `returnedPromise` is:
    38) already-rejected
    39) a pseudo-promise
  `promise1` is rejected, and `returnedPromise` is:
    40) already-rejected
    41) a pseudo-promise

exports not defined?

Is the source missing a var exports = {} to define exports or is this supposed to be used with some other library that defines the exports?

Thanks.

RSVP.hash + rejections seems strange

Current behaviour

RSVP.hash({
  a: RSVP.resolve(1),
  b: 2,
  c: RSVP.reject(3)
}).fail(function(reason){
  reason === 3
});

This makes sense, but rubs me the wrong way. Essentially, when rejections occur, information can lost. If the behaviour is wrong, or if it is correct but we lack other tools in our tool belt, I'd like to hear about it

(cc @domenic)

[Promises/A+] returning falsy values from onRejected

This does not work:

var promise1 = new RSVP.Promise();
promise1.reject();

var promise2 = promise1.then(null, function () {
  return anyFalsyValue;
});

promise2.then(function (value) {
  assert(value === anyFalsyValue);
});

Cannot find module 'lib/rsvp'

Might be user error. Happens in 1.1.1 and 1.2.0.

Installing rsvp via npm. Checking inside of the node_modules/rsvp installation where index.js is located and it calls

module.exports = require('lib/rsvp');

There is no lib directory in that folder.

Is there another way I should be loading this other than

var RSVP = require( 'rsvp' );

Error print out is below

module.js:337
    throw new Error("Cannot find module '" + request + "'");
          ^
Error: Cannot find module 'lib/rsvp'
    at Function._resolveFilename (module.js:337:11)
    at Function._load (module.js:279:25)
    at Module.require (module.js:359:17)
    at require (module.js:375:17)
    at Object.<anonymous> (/Users/jlembeck/code/image-resize-test/node_modules/rsvp/index.js:1:80)
    at Module._compile (module.js:446:26)
    at Object..js (module.js:464:10)
    at Module.load (module.js:353:31)
    at Function._load (module.js:311:12)
    at Module.require (module.js:359:17)

npm

.npmignore /lib is a bad idea since that tells the npm website not to store anything from your lib folder

Bit confused

I don't really know how to install this library.

I am trying to use basket.js that requires rsvp.js

I have placed the JS file(s) and included them in a script, but my browser is complaining about the import { Promise } from .... lines

Firefox reports the error:
SyntaxError: import is a reserved identifier

What are the dependencies? Do I need to build anything?

It seems that I can't just download the rsvp.js files and drop them in...

Thanks for any advise! Chris

Latest pull-request breaks async-testing?

The pull-request (59a869e) that fixes async/rethrow lacking also changes rsvp/async and that change also breaks tests like this:

describe 'something', ->
  async = new AsyncSpec @
  async.it 'should works but not?', (done) ->
    done()

I'm using RSVP with router.js, so I just update my rsvp-latest.js
file directly from the S3 build.

Following the same strategy used in rsvp/rethrow I just change this:

function useSetTimeout() {
  var local = (typeof global === "undefined") ? this : global;

  return function(callback, arg) {
    local.setTimeout(function() {
      callback(arg);
    }, 1);
  };
}

And now everything works nice but...

I notice it's quite strange the use of global, local or window in other methods just to access few well-known global methods (?).

What do you think?

cc: @twokul

[Promises/A+] passing truthy non-functions to `then` should not affect the behavior

These tests fail:

 3.2.6.4: If `onFulfilled` is not a function and `promise1` is fulfilled, `promise2` must be fulfilled with the same value.
   `onFulfilled` is `5`
   `onFulfilled` is an object
 3.2.6.5: If `onRejected` is not a function and `promise1` is rejected, `promise2` must be rejected with the same reason.
   `onRejected` is `5`
   `onRejected` is an object

No longer passes promises tests

With the addition of the fulfillment callback tests (domenic/promise-tests#8), rsvp.js no longer passes the promises tests on https://github.com/domenic/promise-tests.

I suggest to use a stickyonce option for the event in in the EventTarget that all future event handlers added will trigger even if the event handler is added after the event has been triggered. The event handlers will trigger at most once and are removed from the array of callbacks after they have been triggered.

promise:resolved and promise:failed should both be such events.

Alternatively, check isResolved and isRejected when Promise#then is called.

RSVP.all should validate input

I accidentally passed in two promises like RSVP.all(a, b) instead of the proper RSVP.all([a, b]).

Expected behavior: RSVP should raise an error that it expects something array-like.

Actual behavior: RSVP returns a promise that never gets fulfilled.

bower support

I used to install rsvp.js with bower, but I can't anymore since "dist" has been removed from the repo. Any plans to add that back in?

NPM Version Bump

Looks like npm has 1.2.0 as it's latest. Mind bumping it to 2?

Make the repo a proper npm package

It would be great if we can directly npm install this repo, otherwise we have to use the public package, which is still of version 1.2.0.

Typos in README.md

In the example XHR2 wrapper,
1.) XMLHTTPRequest should be XMLHttpRequest
2.) client is missing a send() call, maybe after setRequestHeader. Trying to execute the code does nothing!

trigger vs. emit

The most common EventTarget (ie. EventEmitter) API pattern to emerge seems to favor "emit" over "trigger", perhaps it's early enough to switch the API to match?

Cut a new release

  • update changelog
  • push to NPM
  • verify cross browser
  • ensure ember compatibility
  • ensure other things (like component work)

"Always" suggestion

I just wanted to know if there is any interest on apply an "always" function to the Promise implementation, or it is out of scope.

promise.then(function(value) {
  // success
}, function(value) {
  // failure
}, function(value) {
  //always
}); 

setImmediate (and MessageChannel) broken on IE10

There's a bug in IE10 that makes setImmediate (and MessageChannel) practically useless on IE10 Mobile, and somewhat unreliable on IE10 Desktop. Simply adding a spin.js spinner on our login page caused Q promises to stop working on IE10 Mobile.

I wrote a detailed description of the bug in my blog: http://codeforhire.com/2013/09/21/setimmediate-and-messagechannel-broken-on-internet-explorer-10/

As a workaround, we had to disable both setImmediate and MessageChannel in order to get Q promises to work:
window.setImmediate = undefined;
window.MessageChannel = undefined;

RSVP.js seems to use setImmediate if present, so it's affected as well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.