• Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
MagicMirror Forum
  • Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
A New Chapter for MagicMirror: The Community Takes the Lead
Read the statement by Michael Teeuw here.

How to best process an [object Promise]?

Scheduled Pinned Locked Moved Development
9 Posts 4 Posters 2.7k Views 4 Watching
Loading More Posts
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • E Offline
    E3V3A
    last edited by E3V3A Feb 24, 2018, 10:23 AM Feb 24, 2018, 10:22 AM

    I have an API that is returning a JSON object as an [object Promise]. At first I was completely cluless to what this was. I now understand it’s because the API is using some asynchronous function to obtain and present the data. I have spent the last day or two to reading up about this. In particular about Promises, async/await, fetch/catch, and even Generators.

    But since I’m completely new to this kind of JS programming, I’m rather overwhelmed by the various kinds of methods used for doing this. I could need a small hint of guidance for what to look into. Basically a super simple crash-course to get people like me started in the framework of MM modules. In addition, I’ve read that even seasoned developers get this wrong regularly.

    What I think I need to add in my node_helper is:

    • read the config file to get an option to be used in the API call
    • make the promised API call
    • wait for correct JSON response from API call
    • push JSON to MMM-module

    All the above need to be repeated on a regular interval. (I’m not sure this “polling” need to be implemented separately here, or if the MM config.js reload mechanism is enough.

    What is the simplest method to implement that?
    I’d love to hear from what you guys think.

    PS. I’ve read that async/await is syntactically simpler to use.

    "Everything I do (here) is for free – altruism is the way!"
    MMM-FlightsAbove, MMM-Tabulator, MMM-Assistant (co-maintainer)

    T 1 Reply Last reply Feb 24, 2018, 3:17 PM Reply Quote 0
    • T Offline
      tbbear Module Developer @E3V3A
      last edited by Feb 24, 2018, 3:17 PM

      @E3V3A said in How to best process an [object Promise]?:

      I have an API that is returning a JSON object as an [object Promise]. At first I was completely cluless to what this was. I now understand it’s because the API is using some asynchronous function to obtain and present the data. I have spent the last day or two to reading up about this. In particular about Promises, async/await, fetch/catch, and even Generators.

      But since I’m completely new to this kind of JS programming, I’m rather overwhelmed by the various kinds of methods used for doing this. I could need a small hint of guidance for what to look into. Basically a super simple crash-course to get people like me started in the framework of MM modules. In addition, I’ve read that even seasoned developers get this wrong regularly.

      What I think I need to add in my node_helper is:

      • read the config file to get an option to be used in the API call
      • make the promised API call
      • wait for correct JSON response from API call
      • push JSON to MMM-module

      All the above need to be repeated on a regular interval. (I’m not sure this “polling” need to be implemented separately here, or if the MM config.js reload mechanism is enough.

      What is the simplest method to implement that?
      I’d love to hear from what you guys think.

      PS. I’ve read that async/await is syntactically simpler to use.

      Hi maybe i can help. Have a look at the node_helper.js in the MMM-NOAA modules. Their i use the google translate api which also gives back a promise. U can try the solution i useed.

      Robert the Bear

      E 1 Reply Last reply Feb 24, 2018, 9:47 PM Reply Quote 0
      • E Offline
        E3V3A @tbbear
        last edited by Feb 24, 2018, 9:47 PM

        @tbbear Hi! Thank you, but that is quite an extensive code. Can you pinpoint where you do this?

        "Everything I do (here) is for free – altruism is the way!"
        MMM-FlightsAbove, MMM-Tabulator, MMM-Assistant (co-maintainer)

        T N 2 Replies Last reply Feb 24, 2018, 9:51 PM Reply Quote 0
        • T Offline
          tbbear Module Developer @E3V3A
          last edited by Feb 24, 2018, 9:51 PM

          @E3V3A of course no problem gimme a ffew minutes

          Robert the Bear

          1 Reply Last reply Reply Quote 0
          • N Offline
            ninjabreadman @E3V3A
            last edited by ninjabreadman Feb 24, 2018, 10:18 PM Feb 24, 2018, 10:16 PM

            @E3V3A I don’t think there’s a reload mechanism in MM’s config.js. For example, you can have an updateInterval variable in the module config, but it’s the module’s job to then implement the refresh – it isn’t done automagically by MM.

            See the code for the default compliments module for where it uses this.config.updateInterval to call setInterval() with updateDom() (to set a timer to reload the DOM after a delay) all within its start() function.

            Problem with config or JavaScript? Copy/paste it into JSHint.
            Check out the detailed walkthroughs on install, config, modules, etc.

            M 1 Reply Last reply Feb 25, 2018, 12:00 AM Reply Quote 2
            • M Offline
              Mykle1 Project Sponsor Module Developer @ninjabreadman
              last edited by Feb 25, 2018, 12:00 AM

              @ninjabreadman said in How to best process an [object Promise]?:

              automagically

              Absolutely the best term I have heard to date. :-)

              Create a working config
              How to add modules

              E 1 Reply Last reply Feb 25, 2018, 9:42 AM Reply Quote 0
              • E Offline
                E3V3A @Mykle1
                last edited by Feb 25, 2018, 9:42 AM

                @Mykle1 said in How to best process an [object Promise]?:

                @ninjabreadman said in How to best process an [object Promise]?:

                automagically

                Absolutely the best term I have heard to date. :-)

                :) Especially in this context! I’m only now starting to understand why it’s called a magic mirror… Whatever you guys manage to create, it seem to have been done by development magic…

                But, anyway, my problem is surely just a lack of conceptual and technical knowledge.

                In my node_helper.js I was tryign to do this:

                const NodeHelper = require("node_helper");
                const fs = require('fs');
                const async = require('async');
                const radar = require('radar-api'); // This API return improper JSON
                
                module.exports = NodeHelper.create({
                ...
                    async function radarPing() {
                        console.log("ENTER (inside)");
                        try {
                            const ping = await radar(-8.20917,114.62177,-9.28715,115.71243);
                            console.log("GOT DATA: ", await ping);
                            return await ping;
                        } catch(error) {
                            console.log("API ERROR: ", error);
                        }
                        //return "None";
                        console.log("EXIT (inside)");
                    },
                
                    readData: function() {
                        var radarData = "";
                        radarData = radarPing();
                        console.log("The DATA:\n" + radarData);
                ...
                

                but that ended up with some weird errors, like:

                            const ping = await radar(-8.20917,114.62177,-9.28715,115.71243); 
                                               ^^^^^
                SyntaxError: Unexpected identifier
                    at Object.exports.runInThisContext (vm.js:76:16)
                    at Module._compile (module.js:528:28)
                

                Since, I’ve only started to learn about Promises, sync/await, just 2 days ago, I must be missing a lot. Because all the examples I’ve seen, are using more or less this way of writing.

                So how the eeek do I make sure that what is returned by the api/poll function, is actual data and not an [object Promise], and how can I handle the Promise { } that is returned in advance?

                I’m overwhelmed…

                "Everything I do (here) is for free – altruism is the way!"
                MMM-FlightsAbove, MMM-Tabulator, MMM-Assistant (co-maintainer)

                1 Reply Last reply Reply Quote 0
                • E Offline
                  E3V3A
                  last edited by Feb 25, 2018, 9:46 AM

                  I also tried another variant, but that failed too:

                      radarPing: function() {
                          console.log("ENTER (inside)");
                          try {
                              var ping = radar(-8.20917,114.62177,-9.28715,115.71243); 
                              ping.then({
                              return ping;
                              //...
                              });
                              console.log("GOT DATA: ", ping);
                              //return await ping;
                          } catch(error) {
                              console.log("API ERROR: ", error);
                          }
                          //return "None";
                          console.log("EXIT (inside)");
                      },
                  
                      readData: function() {
                          var radarData = "";
                          radarData = this.radarPing;
                          console.log("The DATA:\n" + radarData);
                  ...
                  

                  "Everything I do (here) is for free – altruism is the way!"
                  MMM-FlightsAbove, MMM-Tabulator, MMM-Assistant (co-maintainer)

                  1 Reply Last reply Reply Quote 0
                  • E Offline
                    E3V3A
                    last edited by E3V3A Feb 26, 2018, 12:29 PM Feb 26, 2018, 12:27 PM

                    I’ve got a partially working function, but it’s a bit funny. For some reason the call to cleanup the JSON is not liked, because it seem that the actual result is not returned, but the Promise .

                    This is the code snippet:

                    radarPing: function() {
                        console.log("ENTER (inside)");
                        Promise.all([
                            radar(-8.20917,114.62177,-9.28715,115.71243)
                            ]).then(function(results) {
                                var ping = results;
                                console.log("PING1:");
                                console.log(ping);
                                var cleanData = jZen(ping);
                                console.log("PING2: ", cleanData);
                                self.sendSocketNotification("NEW_DATA", ping); //"PING"
                                return cleanData; //ping;
                            });
                        console.log("EXIT (inside)");
                    },
                    
                        readData: function() {
                            //const myfile = 'modules/MMM-FlightsAbove/demo.json'; // The demo API use improper JSON
                            var radarData = "";
                            radarData = this.radarPing();
                            console.log("The DATA:\n", radarData);
                    
                    /*        if ( radarData === "" ) {
                            }
                    */        //let cleanData = jZen(data);
                            //let cleanData = jZen(radarData);
                            let cleanData = radarData;
                            if (isJSON(cleanData) ) {
                                this.sendSocketNotification("NEW_DATA", cleanData);
                            } else {
                                // So WTF is it?
                                console.log("- JSON: false");
                                console.log("- isAO(dirty): " + isAO(radarData));
                                console.log("- isAO(clean): " + isAO(cleanData));
                                console.log("- Data:\n", radarData);
                            }
                        },
                    ...
                    });
                    
                    // To check if something is JSON
                    function isJSON(str) {
                        try { return (JSON.parse(str) && !!str); }
                        catch (e) { return false; }
                    }
                    
                    // To check if something is an Array or Object (parsed JSON)
                    function isAO(val) {
                        return val instanceof Array || val instanceof Object ? true : false;
                    }
                    
                    // --------------------------------------------------------------------------
                    // What:  A dirt simple JSON cleanup function that also compactifies the data
                    // NOTE:  - Only use on flat and trustworthy ASCII JSON data!
                    //        - Cannot handle any characters outside [A-Za-z0-9_\-]. (e.g. UTF-8)
                    //        - Using remote data without further sanitation is a security risk!
                    // --------------------------------------------------------------------------
                    const re1 = /([A-Za-z0-9_\-]+):/gm;  // use const to make sure it is compiled
                    function jZen(juice) {
                        //let re1 = /([A-Za-z0-9_\-]+):/gm; // Find all ASCII words $1 before an ":"
                        //let data = juice;
                        let str = "";
                        str = juice.replace(/\s/gm, '');     // Remove all white-space
                        str = str.replace(/\'/gm, '\"');    // Replace all ' with "
                        str = str.replace(re1, '\"$1\":');  // Replace $1: with "$1":
                        //console.log("Dirty JSON is:\n" + data.toString() );
                        //console.log("Clean JSON is:\n" + str);
                        return str;
                    }
                    

                    The output is:

                    ...
                    ENTER (inside)
                    EXIT (inside)
                    The DATA:
                     undefined
                    - JSON: false
                    - isAO(dirty): false
                    - isAO(clean): false
                    - Data:
                     undefined
                    PING1:
                    [ [ { id: '108be389',
                          timestamp: 1519647028,
                          registration: 'PK-GQL',
                          flight: 'QG8816',
                          callsign: 'CTV8816',
                    ...
                    

                    As you can see, PING2 never happens…

                    "Everything I do (here) is for free – altruism is the way!"
                    MMM-FlightsAbove, MMM-Tabulator, MMM-Assistant (co-maintainer)

                    1 Reply Last reply Reply Quote 0
                    • 1 / 1
                    1 / 1
                    • First post
                      9/9
                      Last post
                    Enjoying MagicMirror? Please consider a donation!
                    MagicMirror created by Michael Teeuw.
                    Forum managed by Sam, technical setup by Karsten.
                    This forum is using NodeBB as its core | Contributors
                    Contact | Privacy Policy