Async await new javascript webpage functions replace AJAX

I don’t have a photon at home but thought I would test the new javascript async inline function used on a webpage to do asynchronous AJAX style calls. The “await” ability removes the callback mess of the normal AJAX call.

Can someone try this code and see if it works with an active photon. Just paste all the code into a webpage file saved with the .html extension.

replace your photon ID and Access token where needed:

<input type=button value="Particle Async Curl Style Request" onclick="{

  (async function () {
     try {
       const myResponse =  await fetch('https://api.particle.io/v1/devices/12345?access_token=c12345')
       myOutput  = await myResponse.json()    
       document.getElementById('myDiv01').innerHTML = await 'Name ' + myOutput.name + ', Connected ' + myOutput.connected

     } catch(error) {
       console.log('Error ' +error);
     }

  })()   // end of inline async function


}">


<div id="myDiv01">...</div>
<hr><br><br>

Returned string and identifiers<br>
{
  "id": "0123456789abcdef01234567",
  "name": "gongbot",
  "connected": true,
  "variables": {
    "Gongs": "int32"
  },
  "functions": [
    "gong",
    "goto"
  ],
  "cc3000_patch_version": "1.29",
  "product_id": 0,
  "last_heard": "2015-07-17T22:28:40.907Z",
  "system_firmware_version": "0.7.0"
}

Works for me (connected = true).
But to test it you won’t need a Photon at home, after all you are just asking the cloud about what it knows of the device - connected or not :wink:

Shouldn’t other cloud functions work as well. Can’t you also call a function using the same method?

I see, I thought you just wanted that exact script tested.
I can try with a Particle.variable() as this uses a GET request just as the device info request your tried - and that works too.

1 Like

Thanks @ScruffR. Nothing wrong with AJAX commands with callbacks, they are just a bit difficult to understand and teach to others.The above commands are a bit easier to understand the flow of information and for beginners to write.

I assume all the cloud API commands at https://docs.particle.io/reference/api/ can be done this way without having to wait for a web page refresh. Just remember not to hard code your device ID and Access Token into the webpage.

Perhaps someone can post some working code that gets a variable, etc.

That's nothing else than what you have but with the variable name added to the path

       const myResponse =  await fetch('https://api.particle.io/v1/devices/<DeviceID>/<VarName>?access_token=<AccessToken>')
1 Like

Been looking at this again. fetch using async and await is really very easy to work with, however I can’t seem to get a function going on the photon.

Here is my Photon .INO


void setup() {
    pinMode(D7, OUTPUT);
    Particle.function("doAll", doAllFunction);   
}

void loop() {

}

int myReturn = 0;

int doAllFunction(String myParams) {
    if  (myParams == "toggleLED"){
        digitalWrite(D7, !digitalRead(D7));
        myReturn = digitalRead(D7);    // just so it is either 0 or 1
        Particle.publish("Received Params: " + String(myParams), "Returned: " + String(myReturn), 60, PRIVATE);  

    } else 
    
    if (myParams == "photoResistor"){
        myReturn = analogRead(A0);   
        Particle.publish("Received Params: " + String(myParams), "Returned: " + String(myReturn), 60, PRIVATE);  
    } else 
    
        {
            myReturn = -1;   // showing an incorrect argument
        }
    return myReturn;                                
}

so this curl command would work, with correct ID and acces token

curl https://api.particle.io/v1/devices/f1234f1234/doAll -d access_token=c43212c4321c4321 -d arg=toggleLED

but I can’t seem to get a fetch command that posts the equivalent of form data, (which should not be very hard.) here is my code: (using your own access token and device ID)


<form id="formElem">
  <input type="text" name="args" value="toggleLED"><br>
  <input type="text" name="access_token" value="cf7777777777777777"><br>
  <input type="submit">
</form>

<script>
  formElem.onsubmit = async (e) => {
    e.preventDefault();

    let response = await fetch("https://api.particle.io/v1/devices/77777777777777777777/doAll", {
      method: 'POST',
      body: new FormData(formElem)
    });

   document.getElementById('myDiv01').innerHTML = await JSON.stringify(response)
  };
</script>

<div id="myDiv01">...</div>

I can do everything I want using a very old form POST method that sends the formdata to a different target and that works fine, but it is very cumbersome. Anyone any ideas for getting the above code working. Not sure if it is missing headers or what.

Here is my working code. It is kind of pre-AJAX sending the form data to another textarea instead of refreshing the page. I am trying to update the programming style. On this one you have to enter the device ID and access token on the webpage. It works with the above .ino.


<script>
function myConnect(){
    document.myForm.action = 'https://api.particle.io/v1/devices/' + document.all.myDeviceId.value + '/'+ document.all.myFunctionName.value
    document.all.mySend.value = document.myForm.action
    document.myForm.submit();
}
</script>


Device ID: <input id="myDeviceId" name="myCoreID" type=password size=50 placeholder="777777777777777777777"><br>
Function to run: <input id="myFunctionName" name="myFunction"  type=text  value="doAll" >


<form name="myForm" method="POST"  target="myFrameName"><br>
Access Token:<input id="myToken" name="access_token" type=password size=50 placeholder="fc7777777777777777777777777777777777"><br>
Sent Parameter:<input id="myParameter" name="args" type=text value="toggleLED"><br>
</form><br>

<input type="button" style="font-size:25px"  value="Toggle LED" onClick="{
    myConnect();
}"><br><br>


Results show here (may set them hidden if you want!)<br>
<input type=text id="mySend" size=100 value="">
<iframe style="display:inline" width="400" height="200" name="myFrameName" id="myFrameId"></iframe><br>







here is what it looks like

image

Ok. I got it working. Very simple fetch async programming.

<script>

let myId = "7777777777777777777777"
let myFunction = "doAll"
let myAccessToken = "cfe12f77777777777777777777777777777"
let myParameter = "toggleLED"

let particleApi = "https://api.particle.io/v1/devices"
let myUrl = particleApi + "/" + myId + "/" + myFunction

let myConfig = {
	'headers' : {'Content-Type' :'application/x-www-form-urlencoded'},
	'method' : 'POST',
    'body' : 'args='  + myParameter + '&access_token=' + myAccessToken
}

</script>

<input type="button" value="inline" onclick="{

  (async function () {
      const myResponse = await fetch(myUrl, myConfig)
      document.getElementById('myDiv01').innerHTML = await myResponse.text()
  })()   // end of inline async function

}">

<div id="myDiv01">...</div>




reminder it uses this .ino flashed to the photon


void setup() {
    pinMode(D7, OUTPUT);
    Particle.function("doAll", doAllFunction);   
}

void loop() {

}

int myReturn = 0;

int doAllFunction(String myParams) {
    if  (myParams == "toggleLED"){
        digitalWrite(D7, !digitalRead(D7));
        myReturn = digitalRead(D7);    // just so it is either 0 or 1
        Particle.publish("Received Params: " + String(myParams), "Returned: " + String(myReturn), 60, PRIVATE);  

    } else 
    
    if (myParams == "photoResistor"){
        myReturn = analogRead(A0);   
        Particle.publish("Received Params: " + String(myParams), "Returned: " + String(myReturn), 60, PRIVATE);  
    } else 
    
        {
            myReturn = -1;   // showing an incorrect argument
        }
    return myReturn;                                
}

I saw a post that gets JSON data to send but I could not get it working

The above solution as a complete program with local storage for the device ID and the Access Token

<body onload="{
   myStorage1 = localStorage.getItem('myStoredText1')
   if(myStorage1  != null){
      document.getElementById('myToken').value = myStorage1
    }
    myStorage2 = localStorage.getItem('myStoredText2')
    if(myStorage2  != null){
       document.getElementById('myDeviceId').value = myStorage2
    }
}">

Device ID:        <input id="myDeviceId"  type=password size=50 placeholder="777777777777777777777"><br>
Function to run:  <input id="myFunctionName" type=text  value="doAll" ><br>

Access Token:     <input id="myToken"  type=password size=50 placeholder="fc7777777777777777777777777777777777"><br>
Parameter to send:<input id="myParameter"  type=text value="toggleLED"><br>


<input type="button" value="Store Spark Token and ID locally!" onClick="{
   localStorage.setItem('myStoredText1', document.getElementById('myToken').value)
   localStorage.setItem('myStoredText2', document.getElementById('myDeviceId').value)
   alert('Particle Device ID: ' +document.getElementById('myDeviceId').value +'\nAccess Token: '+
          document.getElementById('myToken').value +  ' \nHave been stored')
}"><br><br>


<input type="button" value="Do Photon" onclick="{

(async function () {

let myUrl = 'https://api.particle.io/v1/devices/' +
      document.getElementById('myDeviceId').value + '/' + document.getElementById('myFunctionName').value

let myConfig = {
	'headers' : {'Content-Type' :'application/x-www-form-urlencoded'},
	'method' : 'POST',
    'body' : 'args='  + document.getElementById('myParameter').value + '&access_token=' + document.getElementById('myToken').value
}

      const myResponse = await fetch(myUrl, myConfig)
      document.getElementById('myDiv01').innerHTML = await myResponse.text()
  })()   // end of inline async function

}">

<div id="myDiv01">...</div>

I made a github to show the

  1. curl command
  2. node js fetch
  3. web browser fetch with local storage