1

I am working on a little web front end for a particle photon I have configured as a learning exercise for js.

I am having an error and I can't figure out why.

Earlier in the code I use the particle script to login https://docs.particle.io/reference/javascript/#with-username-password

var particle = new Particle();
var token;

particle.login({username: 'user@email.com', password: 'pass'}).then(
  function(data) {
    token = data.body.access_token;
  },
  function (err) {
    console.log('Could not log in.', err);
  }
);

In this example I use particle.login() and then immediately use .then on it. It works just fine and I get the token I expect.

Next I want to list all my devices, I use the example code from the documentation to do this:

var devicesPr = particle.listDevices({ auth: token });

devicesPr.then(
  function(devices){
    console.log('Devices: ', devices);
  },
  function(err) {
    console.log('List devices call failed: ', err);
  }
);

This also works perfectly. No trouble.

Here is my problem:

I thought to myself "gee, why don't I just get rid of this var devicesPr and just call then on it immediately". So I try:

particle.listDevices({auth: token}).then(
    function(devices){
        console.log('Devices: ', devices);
    },
    function(err) {
        console.log('List of devices call failed: ', err);
    }
);

Now I get an error saying:

init.js:23 List of devices call failed:  {statusCode: 400, errorDescription: "HTTP error 400 from /v1/devices - The access token was not found", error: Error: Unsuccessful HTTP response
    at Request.<anonymous> (http://cdn.jsdelivr.net/particle-api-j…, body: {…}}
init.js:11 API call completed on promise resolve: API KEY

So what I notice is that it seems like the request for the devices list is being performed before the auth token is generated. I suppose that makes sense as a possibility, since the documentation for promises keep mentioning they are asynchronous.

I am just confused why I don't see the same possible error when I make it a variable first and then call .then on it? Does it somehow know to wait for the auth token to exist if I store the promise to a variable first?

Thanks!

Full trouble code as I am running it:

"use strict";

//var Particle = require('particle-api-js');
var particle = new Particle();
var token;


particle.login({username: 'MYEMAIL', password:'MYPASSWORD'}).then(
  function(data){
    token = data.body.access_token;
    console.log('API call completed on promise resolve: ', token);
  },
  function(err) {
    console.log('API call completed on promise fail: ', err);
  }
);

particle.listDevices({auth: token}).then(
    function(devices){
        console.log('Devices: ', devices);
    },
    function(err) {
        console.log('List of devices call failed: ', err);
    }
);

1 Answers1

2

You're not chaining listDevices with the token gotten from particle.login - you're calling particle.listDevices synchronously, before token has been populated. The request to get the token may have been sent, but the asynchronous .then that populated token surely hasn't run yet.

Instead, use .then to chain listDevices after the particle.login, like this:

var particle = new Particle();
particle.login({username: 'MYEMAIL', password:'MYPASSWORD'})
  .then(data => {
    const token = data.body.access_token;
    console.log('API call completed on promise resolve: ', token);
    // Return the listDevices promise so `.then` can be called on it below:
    return particle.listDevices({auth: token});
  })
  .catch(err => console.log('API call completed on promise fail: ', err))
  .then(devices => console.log('Devices: ', devices))
  .catch(console.log('List of devices call failed: ', err));
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • This makes sense. I will read up on the notation with the arrow you are using. However, I am still confused why chaining the .then immediately vs assigning it to a variable first produced a different result? Did I just luck out? – test_please_ignore Jun 03 '18 at 04:34
  • No, if you assign it to a variable and call `then` on the variable, it should work just as well. `then` (and `catch`) returns a Promise, after all. – CertainPerformance Jun 03 '18 at 06:16