rsvp.js
A lightweight library that provides tools for organizing asynchronous code
Ember controllers are promise-aware, in that the model can be a promise. For an ArrayController you could have a promise to an array, but what if you have an array containing promises?
See this JSFiddle for an example http://jsfiddle.net/7QSZ6/
Why do I need this? We have a Hypermedia (HAL) API with pagination, so if I request a collection of 500 items I get back the first 50 items, with a link to the next 50, and the total count.
I would like to create an array-like object based on Ember.Array that lazily loads consecutive pages. But since loading is async objectAt would have to return a promise that resolves when the element arrives.
Roughly in pseudocode
MyArray = Ember.Object.extend(Ember.Array({
length: 500,
retrieved: 50,
objectAt: function(i) {
if (i > this.get('retrieved')) {
retrievePageFor(i);
}
return this.get('promiseArray')[i];
},
retrievePagesFor: function(i) {
// request pages until we have a value for index i
// update 'retrieved'
// populate 'promiseArray' with promises that resolve when the data arrives
}
}));
Update:
One way is to do it "manually" by using PromiseProxyMixin, e.g. http://jsfiddle.net/Au7LC/1/
Source: (StackOverflow)
I have a route like following where it builds the data from multiple rest calls.
App.IndexRoute = Ember.Route.extend({
model: function() {
var id = 1; //will get as url param later
var modelData = {ab:{},ef:{}};
return ajaxPromise('https://url1/'+ id +'?order=desc').then(function(data){
modelData.ab = data.items[0];
return ajaxPromise('https://url2/'+ id +'/?order=desc').then(function(data){
modelData.ab.x = data.items;
return modelData;
})
});
}
});
My ajaxPromise function is as follows:
var ajaxPromise = function(url, options){
return Ember.RSVP.Promise(function(resolve, reject) {
var options = options || {
dataType: 'jsonp',
jsonp: 'jsonp'
};
options.success = function(data){
resolve(data);
};
options.error = function(jqXHR, status, error){
reject(arguments);
};
Ember.$.ajax(url, options);
});
};
Now the issue is i know that i can use RSVP.all with promise instances but the data returned from these url has to be set to model object like above.
Also there may be few more rest calls which require data from other rest call. Is there any other way i can handle this promises.
PS: data is required right away for a single route
Source: (StackOverflow)
I'm writing a promise-based method which takes one parameter and returns an array of values in the next step. Something like this:
foo(a).then(function (arr) {});
Inside my method foo
I'm doing something like this:
foo = function (a) {
...
// this will return my array
function returnArray(my_return_array) {
return RSVP.all(my_return_array).fail(console.log);
}
return requestBundleElements(a)
.then(assembleReturnArray)
.then(returnArray)
.fail(console.log);
};
I'm wondering if it is possible to pass back arguments
instead of an array
by calling apply
. So I could add another step in my promise chain and do:
return requestBundleList(setLoadingOrder(module_list))
.then(assembleReturnArray)
.then(returnArray)
.then(returnArguments)
.fail(console.log);
with:
function returnArguments(my_result_array) {
//... "apply" something here
}
Question:
But as I don't have access to the "next" callback method, I can't apply
. Is there any way to send back a list of parameters instead of an array to the next step?
Source: (StackOverflow)
I've got a controller method that takes a string argument so I can test if a user has a capability. The user has many roles and the roles has an array of permissions attached that we need to check if it contains the capability. I know this is overly verbose, but for the sake of understanding, I've left it so. Will refactor later...
App.WorkspaceIndexController = Ember.Controller.extend({
userCan: function(capability) {
var userHasCapability = false;
var userPromise = this.get('session.user');
var rolesPromise = userPromise.then( function(user) {
return user.get('roles');
});
var filteredRolesPromise = rolesPromise.then(function (roles) {
return roles.filter(function (role) {
return role.get('workspace') === self.get('workspace');
});
});
filteredRolesPromise.then(function (filteredRoles) {
return filteredRoles.forEach(function (role) {
userHasCapability = _.contains(_.flatten(role.get('permissions'), 'name'), capability);
});
});
return userHasCapability;
},
...
});
The problem I'm having, is that I need the method to return a boolean if the user has the permission. This returns false every time. Am I setting the userHasCapability property improperly, or is there something else I should be doing to return the value?
Source: (StackOverflow)
I am working on a demo showing the error handling in promises using rsvp.js. Everything seemed fine, till I used the CDN url for rsvp.js in a tag. Now since I have require.js for module loading in my application, I tried loading the rsvp.js module via require js syntax. In the Chrome network tab, I see the rsvp.js module getting loaded properly as well, but I get the below error in console,
Uncaught ReferenceError: RSVP is not defined.
require(["bootstrap","js/rsvp"], function(bootstrap,rsvp) {
$(document).ready(function () {
function getEmployeeDetails() {
var radioValue1 = $("input[name='option1']:checked").val();
var requrl;
if (radioValue1 == "fail") {
requrl = "../../../testservice/getEmployeeIdss";
} else {
requrl = "../../../testservice/getEmployeeId";
}
return new RSVP.Promise(function (resolve, reject) {
$.ajax({
url: requrl,
success: function (response) {
try {
$('#successBoard').append("<b> <i> Ajax Call 1 Succeeded! </i> </b><br/>" + "Employee ID:" + response.stuId + "<br/>");
resolve(response.stuId);
} catch (e) {
reject(e);
}
},
error: function (xhr, ajaxOptions, thrownError) {
console.log('Ajax 1 failed : Rejecting Promise 1');
$('#errorBoard').append("<b> <i> Ajax 1 failed : Rejecting Promise 1</i> </b><br/>");
reject(thrownError);
}
});
});
}
Source: (StackOverflow)
When I do something like:
Ember.$.getJSON(url)
.then(function(response){
return Ember.RSVP.all(response.map(Ember.$.getJSON))
})
.then(function(response){
// this is where the oddity begins
console.log(response)
})
in the model
hook in my application router on my local environment (Ember 1.13.5), I get a weird response, in the second then()
's response, like:
Promise: {
_id: 48
_label: undefined
_result: Array[1]
_state: 1
_subscribers: Array[0]
__proto__: Promise
}
I can do a response.then()
in the second then
to get the response I'm looking for, but that is less than ideal since I would like to chain promises.
I tried to set up the same example on JSBin, using Ember.run.later
to act as promises: JSBin Example. The methodology seems to work fine here.
Am I missing something?
Source: (StackOverflow)
Re: https://github.com/tildeio/rsvp.js
What's the best way to integrate RSVP.js with jQuery's $.ajax? After doing some reading and research, I see that in Ember there is active development of a wrapper around it... https://github.com/emberjs/ember.js/pull/4148
Anyone with experience with this use-case of promises?
I'm using RSVP.js because I'm handling a dynamic array of promises through the .all() method.
Each of those promises from the array has its own promise that is fulfilled once its done polling for data from a function recursively. I'm having issues considering how I should structure the code.
The use-case if you're interested is that I'm sending an AJAX request to my API for a report pertaining to a specific resource that returns a list of URL endpoints that it should hit for more report data about its child resources. Each of those resources then returns a JSON object with report data for a specific day and another URL with params for the next day (or group of days). This then keeps polling for data with "next" from the same endpoint until there's nothing left.
Thanks in advance to anyone who can help!
Also, if you have any guidance on how to format this code so it's more readable and maintainable, I'd love to hear.
Code:
url = "http://localhost:3000/api/foo_resources/1/reports/bar"
var headers = {
"Accept": 'application/vnd.xps+json; version=1', // Headers for API access
"X-User-Email": 'example@company.com',
"X-User-Token": '1234abcd',
}
$.ajax({
type: 'GET',
url: url,
headers: headers,
dataType: 'json',
xhrFields: {
withCredentials: true
}
}).then(function(response) {
// the ajax request would return a long list of bucket like this with endpoints to hit {
// {
// "buckets": [
// "http://localhost:3000/api/foos_nested_resources/1/reports/bar"
// "http://localhost:3000/api/foos_nested_resources/2/reports/bar"
// "http://localhost:3000/api/foos_nested_resources/3/reports/bar"
// ]
// }
var promises = response.buckets.map(function getReportData(bucket) {
return new RSVP.Promise(function(resolve, reject) {
var recursiveRequest = function(bucket) {
$.ajax({
type: 'GET',
url: bucket,
headers: headers,
dataType: 'json',
xhrFields: {
withCredentials: true
}
// This is the report that comes back, obviously truncated significantly for this example
// {
// reports: [
// { id: 1, datapoint_a: 5438, datapoint_b: 1389 },
// { id: 2, datapoint_a: 4336, datapoint_b: 2236 }
// ],
// next: "http://localhost:3003/api/nexted_foo_resources/1/reports/bar?ends=2014-02-06&starts=2014-01-24"
// }
}).done(function(response) {
$.merge(reports, response.reports); // I could use concat here but I prefer readability
if (response.next) {
recursiveRequest(response.next);
} else {
resolve(reports);
}
}).error(function(error) {
reject(error);
});
};
recursiveRequest(bucket);
});
});
RSVP.all(promises).then(function(data) {
console.dir(data);
}).catch(function(error) {
console.dir(error);
})
})
Source: (StackOverflow)
I'm using nodeJS, running express4 framework to create an API. I am using RSVP.js for promises.
worker.getFamilies is called by an external module, not reflected here. The caller expects back an object with results.
Inside worker.getFamilies:
- I am querying mongoDB using mongoose (works, we get results back)
I am using a promise to get the response object from mongoose when its available. That works.
Then I try to return JSON.stringify(results); to the caller of worker.getFamilies and that doesnt work. The caller gets back "undefined". please help.
var worker = exports;
var RSVP = require('rsvp');
var getFamiliesFromDB = function(DBconnection){
var promise = new RSVP.Promise(function(resolve, reject){
DBconnection.find({} ,{limit:10, sort: [['_id',-1]]}).toArray(function(e, results){
console.log('results:', results);
resolve(results);
});
});
return promise;
}
worker.getFamilies = function(DBConnection){
getFamiliesFromDB(DBConnection).then(function(results){
//this works
console.log('here are the fams from the promise', results);
//this doesnt work like i want it to
return JSON.stringify(results);
});
};
Source: (StackOverflow)
I'm trying to make use of _super in the handler of a Promise inside of a Controller action, but it doesn't work because it seems to lose the correct chain of functions.
ApplicationRoute = Ember.Route.extend SimpleAuth.ApplicationRouteMixin,
actions:
sessionAuthenticationSucceeded: ->
@get("session.user").then (user) =>
if @get("session.isTemporaryPassword") or not user.get "lastLogin"
@transitionTo "temp-password"
else
@_super()
I want to revert to the Mixin's default behavior on the else
but I need to resolve user
asynchronously before I can do a conditional statement. I tried:
ApplicationRoute = Ember.Route.extend SimpleAuth.ApplicationRouteMixin,
actions:
sessionAuthenticationSucceeded: ->
_super = @_super
@get("session.user").then (user) =>
if @get("session.isTemporaryPassword") or not user.get "lastLogin"
@transitionTo "temp-password"
else
_super()
and
ApplicationRoute = Ember.Route.extend SimpleAuth.ApplicationRouteMixin,
actions:
sessionAuthenticationSucceeded: ->
@get("session.user").then (user) =>
if @get("session.isTemporaryPassword") or not user.get "lastLogin"
@transitionTo "temp-password"
else
@_super.bind(@)()
Neither works.
This answer claimed this should work as of 1.5.0, but I'm using 1.7.0-beta.5 and it's no go. Is there a way to get this to work, even in terms of approaching this differently?
Source: (StackOverflow)
http://promisesaplus.com/
Finally, the core Promises/A+ specification does not deal with how to
create, fulfill, or reject promises, choosing instead to focus on
providing an interoperable then method. Future work in companion
specifications may touch on these subjects.
As a functional developer, I usually deal with monads and operators like point
bind
map
or flatMap
to chain calls that are wrapped inside some monad box.
According to this question Js Deferred/Promise/Future compared to functional languages like Scala, the map
and flatMap
operators seems to be melted together under then
in the js spec, probably because it would not make so much sense to provide both in a dynamically typed language like Js (?) and it is more convenient to use and remember a single operator.
So far so good, there's a then
operator (that doesn't seem to always be properly implemented)
But why do the promise create / fulfill / reject is not part of the spec?
It's like just having an half a monad :(
It seems I'm not the only one to complain
Typically, my problem is:
- I want to create a JS library
- I want to expose a promise-based API
- I want the client to choose the promise implementation he wants to use
Now what am I supposed to do?
I can create promises in my library like
Q.fcall(function () {
return 10;
})
Ok cool, I just coupled my library to Q :(
So, is there any solution to this problem?
How a library author is supposed to create the promises he exposes to the API without coupling to the implementation?
Is there some license-free minimum viable promise A+ library that we can embed in our libraries or something?
What are the reasons behind this spec choice?
Source: (StackOverflow)
I'm trying to execute a promise inside Ember.RSVP.all
App.Foo = Ember.Object.create({
bar: function() {
var configuration = ajaxPromise("/api/configuration/", "GET");
Ember.RSVP.all([configuration]).then(function(response) {
//do something with the response in here
});
}
});
But because my integration test mocks the xhr w/out a run loop the test fails with the expected error "You have turned on testing mode, which disabled the run-loop' autorun"
So I wrapped the RSVP with a simple ember.run like so
App.Foo = Ember.Object.create({
bar: function() {
var configuration = ajaxPromise("/api/configuration/", "GET");
Ember.run(function() {
Ember.RSVP.all([configuration]).then(function(response) {
//do something with the response in here
});
});
}
});
But I still get the error for some odd reason. Note -if I run later it's fine (this won't work though as I need to exec the async code for this test to work correctly)
App.Foo = Ember.Object.create({
bar: function() {
var configuration = ajaxPromise("/api/configuration/", "GET");
Ember.run.later(function() {
Ember.RSVP.all([configuration]).then(function(response) {
//do something with the response in here
});
});
}
});
Here is my ajaxPromise implementation -fyi
var ajaxPromise = function(url, type, hash) {
return new Ember.RSVP.Promise(function(resolve, reject) {
hash = hash || {};
hash.url = url;
hash.type = type;
hash.dataType = 'json';
hash.success = function(json) {
Ember.run(null, resolve, json);
};
hash.error = function(json) {
Ember.run(null, reject, json);
};
$.ajax(hash);
});
}
How can I wrap the Ember.RVSP inside my ember run w/out it throwing this error?
Update
here is my test setup (including my helper)
document.write('<div id="ember-testing-container"><div id="wrap"></div></div>');
App.setupForTesting();
App.injectTestHelpers();
test("test this async stuff works", function() {
visit("/").then(function() {
equal(1, 1, "omg");
});
});
The only part I've left out is that I'm using jquery-mockjax so no run loop wraps the xhr mock (and in part that's why I like this library, it fails a test when I don't wrap async code with a run loop as the core team suggests)
Source: (StackOverflow)
I'm using the RSVP library distributed inside Ember.js and I'm trying to figure out the correct pattern for reporting fatal errors inside a promise -- particularly I want to inform of something that's almost certainly the result of a programming error due to api misuse and I want to do it in a LOUD way. I'm new to promises and javascript in general, hopefully this question makes sense
Here's a simple example (in coffeescript):
doAsync = (arg, callback) ->
throw new Error('you gave me a way bad arg, I fail for you!')
promiseReturningApi = (data) ->
return new Ember.RSVP.Promise (resolve, reject) ->
callback = (err, resp) ->
if err then reject(err)
else resolve(resp)
doAsync(data, callback)
Now lets say I've identified an error that there's no possible way to recover from which occurred inside doAsync -- I want to make sure this error gets reported even if the caller neglected to attach an error handler because it almost certainly only resulted because the caller invoked the api function in an incorrect way
I came across the idea of using setTimeout within a rejection handler to ensure the error gets raised from somewhere even if the caller doesn't attach an error handler to the promise
failLoud = (err) ->
if err.isProgrammerError
setTimeout () ->
throw err
throw err
promiseReturningApi = (data) ->
promise = new Ember.RSVP.Promise (resolve, reject) ->
callback = (err, resp) ->
if(err) then reject(err)
else resolve(resp)
doAsync(data, callback)
return promise.then(null, failLoud)
Is it considered a reasonable practice to attach such a default error handler to a promise before returning it from my promiseReturningApi? This would allow me to force a stacktrace when the caller does something that can't possibly work -- even though the stacktrace would be a little odd it could make things a bit easier to get started with ...
Even though I called the example promise returning function an 'api' call -- I should add that I'm not writing framework code -- this is rather all within an application. If doAsync were a real-world function, then in my versio of the real-world its pretty likely to be coming from an external party with a new-to-me api -- so it seems pretty likely that I'll misuse it while I'm getting to know it... Meaning I might want to make the pattern something like this
failLoud = (err) ->
if err?.isProgrammerError
setTimeout () ->
throw err
throw err
promiseReturningApi = (data) ->
promise = new Ember.RSVP.Promise (resolve, reject) ->
callback = (err, resp) ->
if(err) reject(err)
resolve(resp)
try
doAsync(data, callback)
catch err
err.isProgrammerError = true
throw err
return promise.then(null, failLoud)
I think what this is doing is forcing an exception to be thrown from somewhere any time that my asynchronous function call invocation itself raises an exception -- such an exception would almost certainly be raised during the argument validation phase of the async call which is most commonly going to be the result of my application code passing in something which doesn't make any sense -- and I want to find out about that as soon as I can. Does this seem like a reasonable pattern to follow to aid in debugging promises used in application code in this context?
Source: (StackOverflow)
I'm new to promises and using the rsvp implementation.
I want to asynchronously read a list of files, then proceed to another task only when all files have been read.
I've got as far as the basic structure to read one file, and chain to the next task:
var loadFile = function (path) {
return new rsvp.Promise(function (resolve, reject) {
fs.readFile (path, 'utf8', function (error, data) {
if (error) {
reject(error);
}
resolve(data);
});
});
};
loadFile('src/index.txt').then(function (data) {
console.log(data);
return nextTask(data);
}).then(function (output) {
//do something with output
}).catch(function (error) {
console.log(error);
});
I want to do something like this:
loadFile(['src/index.txt', 'src/extra.txt', 'src/another.txt']).then( ...
I've seen arrays of promises and hash of promises in the docs, but I don't know which is most relevant, or how to use them. I need an example of their use in the context of my problem above to understand them.
Source: (StackOverflow)
I have a route that pulls in 2 different promises using RSVP like so
model: function() {
return Ember.RSVP.hash(function() {
stuff: App.Thing.find(),
other: this.store.find('appointments', {day: day})
});
}
The challenge is that I have a custom function I bind/invoke in the "then" of the 2nd promise shown above. How can I invoke this when the callback happens along side another promise using RSVP?
Here is the custom callback as it stands today (not inside of RSVP.hash just yet)
function bindContextAndGenerateAvailable(employee, other, appointments) {
return function(filteredAppointments) {
//will take the filtered collection and do something w/ it
//to populate the bound appointments array passed in
}
}
var appointments = Ember.A([]);
this.store.find('appointment', {day: day}).then(function(response) {
Ember.RSVP.all(response.getEach('employee')).then(function(empls){
var filtered = response.filterBy('employee.id', employee);
Ember.RSVP.resolve(filtered).then(bindContextAndGenerateAvailable(employee, other, appointments));
});
});
return appointments;
Source: (StackOverflow)
Re: https://github.com/tildeio/rsvp.js
I have a function called doSomething() that does something for a little while
and then returns an RSVP.Promise. Then, a chain of success and failure callbacks are
registered with the returned promise (see code below). The behavior I expected
was, if the promise is fulfilled, the chain of success callbacks registered with
the promise will be fired, and if the promise is rejected (fails), the chain of
failure callbacks will be fired.
I get the expected behavior for when the promise is fulfilled, but I get a
behavior different than what I expected when the promise is rejected. That is,
the success callbacks are chained and output of one success callback is passed on to
the next success callback in the chain. But it appears the failure callbacks
are not chained. They behave almost like the catch in a try/catch block (see
code and output below).
Can someone explain this behavior? Is this really the way it's suppose to work, or is this
an error in the way rsvp.js handles a rejected/failed promise that has a chain of failure callbacks registered with it? I'm reading the Promises/A+ spec now to try and figure this out, but if someone knows this stuff off the top of their head, would love to hear your explanation. Thanks in advance.
jsfiddle: http://jsfiddle.net/rylie/VYSj7/2/
doSomething() // returns an RSVP.Promise object
.then(
function(message) { console.log("then success 1: " + message); return "from success 1"; }, // success callback
function(message) { console.log("then failure 1: " + message); return "from failure 1"; } // failure callback
)
.then(
function(message) { console.log("then success 2: " + message); return "from success 2"; }, // success callback
function(message) { console.log("then failure 2: " + message); return "from failure 2"; } // failure callback
)
.then(
function(message) { console.log("then success 3: " + message); return "from success 3"; } // success callback
)
.then(
null,
function(message) { console.log("then failure 4: " + message); return "from failure 4"; } // failure callback
)
.then(
function(message) { console.log("then success 5: " + message); return "from success 5"; }, // success callback
function(message) { console.log("then failure 5: " + message); return "from failure 5"; } // failure callback
);
** When the promise is fulfilled (succeeds), this is the output I get and expected:
then success 1: Promise fulfilled!
then success 2: from success 1
then success 3: from success 2
then success 5: from success 3
** When the promise is rejected (fails), this is the output I get:
then failure 1: Promise rejected!
then success 2: from failure 1
then success 3: from success 2
then success 5: from success 3
** This is what I expected (on a rejected/failed promise):
then failure 1: Promise rejected!
then failure 2: from failure 1
then failure 4: from failure 2
then failure 5: from failure 4
Source: (StackOverflow)