EzDevInfo.com

rsvp.js

A lightweight library that provides tools for organizing asynchronous code

Have Ember.ArrayController render an array of promises

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)

Building Model object from multiple rest calls

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)

Advertisements

How to call "apply" in a promise-based setup in Javascript to pass parameters to the next then()?

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)

How do I return the boolean value from this layer-cake of promises?

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)

Uncaught ReferenceError: RSVP is not defined , error while using require.js with rsvp

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)

Chaining promises with Ember.RSVP.all and Ember.RSVP.Promise returning odd results

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)

Integrating array of promises from RSVP.js with jQuery's $.ajax

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)

nodeJS / Express: what's wrong with this RSVP promise?

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)

Calling an Ember _super method from Promise handler

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)

Why do JS Promise A+ create/fulfill/reject not part of the spec?

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)

How to execute Ember.RSVP.all within an ember run loop correctly

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)

acceptable promise pattern for 'LOUD' errors?

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)

How to read multiple files asynchronously with promises, then proceed

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)

How to register a custom callback after Ember.RSVP.hash

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)

How rsvp.js handles rejected promise with chain of failure callbacks

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)