My first App

Started by Carlo Didier, November 20, 2017, 09:35:47 PM

Previous topic - Next topic

Carlo Didier

Ok, I have my first app 99% running.
The code is awkward, contorted, complicated and difficult to understand, but it does what I wanted ... to a point (the 1 missing percent).

If anyone dares have a look, attached is the app. You can download my test database here (75MB zip file): https://drive.google.com/file/d/1W_GPq3wLrx8VvBMRDlKNospEKJLtU5UU/view?usp=sharing

What does it do?
You choose whether you want to run it on the images in two specific categories (see screenshot of my indexing settings), a current selection of images or all images in the database.
When you click the start button, it gets the list of images and for each of them it compares the filename with the text in the descriptions of my WHY|EVENTS categories (the categories are actually selected through the descriptions, not that path).
If the name of an image falls in the range defined by a category description, it is assigned to that category.

What is the missing 1%?
Two things:
First, the progress bar just won't work. For up to ~3000 files the script is so fast you won't need it anyway.
But for more files, it would be nice to have, if just to give the html interface a reason to exist.

Second, upwards of ~20000 files it tends to run out of memory and crash IMatch ... Why?
Look at lines 137-148. I found out that the forEach loop from line 106 runs so fast that the posts from line 137 get all queued. If that was a normal sequential script there would be no problem, but here we are in asynchronicity hell.

If anyone has a good solution, please tell me. I tried a number of things, even consulted with one our web developers (he finally said that these web services were not really adequate for what I want to do - which I knew from the start, so that didn't help me either).

The script contains around 100 lines of effective code (if you don't count empty lines and comments).

For comparison, I also attach my old IM5 database script. Much shorter, simpler and easier to read. And it works perfectly for any number of files ...
Note that I removed other stuff, so you only see the parts that did what the new script does.
There are actually a number of other things done when new/updated files are detected (remember the old script was automatically triggered by those events, no need to do it manually).

thrinn

Carlo,
first of all: Congratulations!

One thought:
At the moment, you have an outer loop over all selected files and an inner loop to probe each file against each category and do the assignment, one file to one category per POST. Would it not be better to switch inner and outer loop? I assume that most of the time multiple files are assigned to the same category, and that the number of categories is significantly lower than the number of files. Therefore, my suggestion is:
- Handle the categories in the outer loop.
- Loop over the files in the inner loop. In the inner loop, push files that should be assigned to the category you work with in the outer loop first to an array.
- After the inner loop, assign all files you collected in the array to the current category in one batch. After all, the v1/categories/assign endpoint is able to assign multiple files at once to a category.
This should drastically reduce the number of POST calls.

I suspect firing 20000 POST requests at (more or less) the same time at IMatch is not ideal...

Thorsten
Win 10 / 64, IMatch 2018, IMA

Carlo Didier

Your idea is correct, Thorsten, but this is just the beginning.

Later on, the category assignment will be one of several modules started within the outer files loop. That's why I turned it that way around.
The main script will always go through all the selected files and do several things, not only this event category assignment.

And performance is not an issue. Even on my nearly 7 years old desktop, running the script against ~5000 files takes less than 7 seconds.

Jingo

Congrats from me as well Carlo... its not easy to learn and code a new language so kudos to you for getting where you are... the more you experiment - the better your skills will become!

Mario

Don't bomb IMWS with thousands of simultaneous requests. This may not only cause your app to malfunction, but also impact IMatch and other apps currently running.
It may also break the browser (AJAX machinery) and/or jQuery (AJAX wrapper) randomly.
These are not designed to manage and maintain thousands of parallel requests. This is not what AJAX is designed for.

It's always better to work in smaller batches.

If you have iterate over 50,000 files and to assign them to one of 100 categories, the good design would be, probably:

1. Setup a data structure holding data for each category:

var cats = []...
{
  catid : number // The id of the cat
  filesA: []  // array with the files to assign
  filesU: []  // array with the files to un-assign
}

1. Iterate over all files. Put their ids into the filesA / filesU arrays of the determined category(ies).

2. Iterate over the categories array and for each object do one POST to update the category.
Instead of 50,000 POSTs you have now only 100.

Needs almost no memory, super-fast, low resource usage.
No crashing browser or excessive memory usage.



-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Sounds like a good solution, Mario.
Still, it would be much much simpler and cause no problems at all if I just could execute the posts sequentially, like in the old script.
If I look back at all the contorsions I had to go through because I can't just wait for a get or post ...

But your solution has a certain elegance, I must admit.

Mario

QuoteStill, it would be much much simpler and cause no problems at all if I just could execute the posts sequentially, like in the old script.
Won't happen. WebService requests are by default asynchronous. The concept of promises and asynchronous processing is extended, becoming one of the core concepts in all modern programming languages. The only way to utilize the multiple processor cores in modern computers. Processor speed is pretty much maxed out, more performance can only come from more cores.

It's so simple to use asynchronous processing.
I demonstrated this in my replies to your many posts this week. The "next()" function, you remember.

Instead of:

var someArray = [];
for (var i = 0; i < someArray.length; ++i) {

  IMWS.get().then(...)

}


you write the doWork function to call itself after the IMWS request has completed - unless all things are processed.

var someArray = [];
var index = 0;

function doWork()
{
  if (index >= someArray.length) {
    // Done.
    // console.log("All done!);
  }
  else  {
      IMWS.get().then(function(response) {
        index++;
        doWork();
      });
  }
}

doWork(); // Process the first element.

console.log("Your app continues");



A few lines lines of code, actually. Works always the same.
But scales super-good. Allows your app to be responsive, react on user input, do window repaints etc.

Note also that most IMWS requests have been written to be batch oriented. They can usually process or return multiple objects/items.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

I know and (finally) have understood all that, but I still find it contorted and complicated because what happens when I have another web call inside the doWork() function? And another one inside that? And another one inside that? And another one inside that? And another one inside that? ... because I have several things that need to be done one after the other. That's what I mean by contorted.

If I need to do Step_1, then Step_2 and then Step_3 in that order and all involve asynchronous IMWS calls. How will I do that?
Will I end up with something like this (and I can't even imagine where and how to correctly place the "var ..." lines):

var someArray = [];
var index = 0;

function doWork_Step_1()
{
  if (index >= someArray.length) {
    // Done.
   doWork_Step_2();
  }
  else  {
      IMWS.get().then(function(response) {
        index++;
        doWork_Step_1();
      });
  }
}

function doWork_Step_2()
{
  if (index >= someArray.length) {
    // Done.
    doWork_Step_3();
  }
  else  {
      IMWS.get().then(function(response) {
        index++;
        doWork_Step_2();
      });
  }
}

function doWork_Step_3()
{
  if (index >= someArray.length) {
    // Done.
    // console.log("All done!);
  }
  else  {
      IMWS.get().then(function(response) {
        index++;
        doWork_Step_3();
      });
  }
}
........


What if I have more steps that need to executed sequentially?

Mario

Quotewhen I have another web call inside the doWork() function? And another one inside that?

Maybe a need to re-design your app?
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Or redefine mathematics?
If step 3 depends on the result of step 2 which depends on the result of step 1, there is no choice of design ...

Mario

I can't help you to solve mathematical puzzles. This is the IMatch community.

If you have to solve problems caused by the way JavaScript performs web requests (this is not related to IMatch, mind) I suggest you use one of the many programming tutorials.
Or maybe switch to a programming language that cannot do asynchronous web requests, Windows PowerShell.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

thrinn

Quote from: Mario on November 21, 2017, 06:10:39 PM
Quotewhen I have another web call inside the doWork() function? And another one inside that?
Maybe a need to re-design your app?
It is difficult and generally frustating (also my experience) to try to force an old-style sequential processing on an app which is asynchronous by nature (assuming it uses web service calls). I also had to rethink how an script should be structured (and am still learning).
But if you need, for example, the result of one IMWS call to prepare a second IMWS and want to start a third IMWS request after the second has finished, you don't necessarily have to nest them. An alternative approach can be chaining. See, for example, https://javascript.info/promise-chaining.

Quotethere is no choice of design ..
There is always a choice  ;)
Thorsten
Win 10 / 64, IMatch 2018, IMA

Mario

Parallel processing of asynchronous requests is also easy.
If you need to wait for all requests to finish before you perform some operation in an app, the jQuery method $.when() makes this easy. It waits for any number of promises.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Quote from: Mario on November 21, 2017, 07:19:23 PMParallel processing of asynchronous requests is also easy.
except when your task to solve is sequential

Quote from: Mario on November 21, 2017, 07:19:23 PMIf you need to wait for all requests to finish before you perform some operation in an app, the jQuery method $.when() makes this easy. It waits for any number of promises.
still another thing to learn ... get's more and more complicated and ugly

Carlo Didier

Quote from: thrinn on November 21, 2017, 06:34:20 PM
But if you need, for example, the result of one IMWS call to prepare a second IMWS and want to start a third IMWS request after the second has finished, you don't necessarily have to nest them. An alternative approach can be chaining. See, for example, https://javascript.info/promise-chaining.
Interesting reading ... sounds like chinese mixed with gaelic and a touch of martian  8)
What's the advantage of replacing three straight lines of code with horribly complex constructs like that?

Simple, straight forward, easy to understand:
a = function1(something)
b = function2(a)
c = function3(b)


The horror version:
new Promise(function(resolve, reject) {

  setTimeout(() => resolve(1), 1000); // (*)

}).then(function(result) { // (**)

  alert(result); // 1
  return result * 2;

}).then(function(result) { // (***)

  alert(result); // 2
  return result * 2;

}).then(function(result) {

  alert(result); // 4
  return result * 2;

});

I don't have the slightest idea where in that code-jungle I'd have to place my code that actually does something ...

Quote from: thrinn on November 21, 2017, 06:34:20 PM
There is always a choice  ;)
:)

Carlo Didier

#15
Quote from: Mario on November 21, 2017, 06:28:37 PMOr maybe switch to a programming language that cannot do asynchronous web requests, Windows PowerShell.

Do you mean that if I had a Powershell script like this:
$arrFiles = Invoke-RestMethod -Uri "http://127.0.0.1:50519/'v1/categories/files?{auth}&path='QUEUES|_new,QUEUES|_modified'&direct=true&sortby='filename'&fields='id,name'"
$arrCategories =  Invoke-RestMethod -Uri "http://127.0.0.1:50519/'v1/categories?{auth}&regexp='desc,^D[0-9]{11}-D[0-9]{11}'&recursive=true&fields='id,name,description,path,children'"

then these two lines would actually be executed sequentially?

Note that the above lines don't work:
Invoke-RestMethod -Uri "http://127.0.0.1:50519/'v1/categories/files?{auth}&path='QUEUES|_new,QUEUES|_modified'&direct=true&sortby='filename'&fields='id,name'"
Invoke-RestMethod : The remote server returned an error: (404) Not Found.
At line:1 char:1
+ Invoke-RestMethod -Uri "http://127.0.0.1:50519/'v1/categories/files?{ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebExc
   eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

Mario

#16
QuoteInvoke-RestMethod -Uri "http://127.0.0.1:50519/'v1/categories/files?{auth}&path='QUEUES|_new,QUEUES|_modified'&direct=true&sortby='filename'&fields='id,name'"

{auth} has no meaning. You need to specify the auth_token you have received on behalf of your authentication request.

Please see the Microsoft PowerShell documentation for information how to do web requests.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

ubacher

QuoteAn alternative approach can be chaining

Thrinn: Could you please regale us with an Imatch sample program. One Simple and one with error checking each call?
(...maybe this coming Christmas??) I think I have seen this in some of your code you posted but skipped it at the time for lack of understanding.

Carlo: most of us are struggling with this need to perform asynchronous calls synchronously. That's because the
type of scripts we write are not typical for a windows/browser based environment.
In a browser oriented script there are few chained calls. The sequential operation is performed by the user clicking buttons etc.
Instead of chaining one uses displaying/hiding/enabling/disabling buttons so the user can only start a new call when the previous one
it depends on has completed. Mind you, this too can quickly get difficult to get right.

I gave up trying to learn javascript thoroughly - I just get the scripts that I am used to working and leave it at that.
Similarly with HTML and bootstrap - my user interfaces are very crude - but then they are just for me anyway.


Mario

A) Linear Programming:

function someFunction()
{
   // bla
}

if (someFunction()) {
  // do work  after someFunction has returned.
}


B) Modern Programming:

function someFunction()
{
    return IMWS.get(...);
}

someFunction().then(response => {
  // do work  after someFunction has returned.
});


Not so different. The modern way just works better when you don't know how long someFunction runs, if you want to do other things like keeping the UI up-to-date or if your program needs to do multiple things at the same time to utilize modern processors better.

Note that JavaScript uses linear programming in 99% of all cases. Only web requests and web workers work asynchronous.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Jingo

It takes time to learn these new languages... I think we all want to jump right in and get immediate results - but that is not always possible with modern languages. 

At work, we have 6 programming languages for our product lines - each homegrown and an extension of each the previous generation.  The older languages were very simple - easy to read and write because they flow using a top to bottom approach.  They also tend to use descriptive functions that one can understand simply by reading the code (ie: If{a then b else c}).  The newer languages are much more complex and use libraries and repeatable functions, objects and methods.  The code does not flow from top to bottom and stack variable "lists" are passed into functions on an iterative basis... thus, the same code can execute 30 times as each list member is passed in and only then does the code flow to the next stage.  Code can also extend to other codesets through includes.... you cannot just read the code and easily determine what's going on (ie: {listset}@[@IFP{a,}@CallFunction,1}@= do this;do that]). 

It generally takes a programmer about 2 years to get proficient in these newer language.... give yourself some time.

Carlo Didier

Quote from: Mario on November 21, 2017, 08:32:25 PMNote that JavaScript uses linear programming in 99% of all cases. Only web requests and web workers work asynchronous.
I know, and I don't blame java script. Would I have the same API there as in the old basic scripting engine, all my scripts together would have been converted in less than a day and still work exactly as before.

But you didn't answer my question about the two Powershell lines. Will they be executed one after the other, meaning that the second line will only be executed when the $arrFiles has received the result in of the first line?

Mario

If this question was directed at me:

For PowerShell support, please contact Microsoft. They know a lot more than me about PowerShell.
There are also tons of communities out there devoted to PowerShell programming.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

#22
Quote from: Jingo on November 21, 2017, 09:16:10 PMgive yourself some time.
Well, the scripting engine in IMatch is supposed to make life easier, not more complicated, right? To be able to easily do things without having a university degree in programming.
Having a very (!) simple task to perform, I'm not willing to invest a relatively gigantic amount of time to get it running again.

And even in the most modern programming languages you can still code linear tasks linearly, as long as you don't introduce asynchronous functions (for which there is absolutely no need in the case of linear tasks).

Where is that old KISS ("Keep It Simple, Stupid!") principle?

Carlo Didier

Quote from: Mario on November 21, 2017, 09:48:40 PM
If this question was directed at me:

For PowerShell support, please contact Microsoft. They know a lot more than me about PowerShell.
There are also tons of communities out there devoted to PowerShell programming.

I know Powershell, but never used it in combination with web services. You said that using Powershell I could make it run linearly, that's why I asked.

ben

I never used the powershell for scripting.
Instead I converted all of my scripts to python. All the web requests can run sequentially.
Converting was kind of a line by line task.

Carlo Didier

Quote from: Mario on November 21, 2017, 02:10:14 PM
If you have iterate over 50,000 files and to assign them to one of 100 categories, the good design would be, probably:

1. Setup a data structure holding data for each category:

var cats = []...
{
  catid : number // The id of the cat
  filesA: []  // array with the files to assign
  filesU: []  // array with the files to un-assign
}

1. Iterate over all files. Put their ids into the filesA / filesU arrays of the determined category(ies).

2. Iterate over the categories array and for each object do one POST to update the category.

Ok, I modified the script to do it that way, but the category/assign  doesn't work.
First I had used the parameter "fileidlist" because it's a list of file IDs that I give it, but then I found out that I have to use the parameter "fileid", even with a list. But it still doesn't work (see attachments).


Carlo Didier

Quote from: ben on November 21, 2017, 10:34:39 PM
I never used the powershell for scripting.
Instead I converted all of my scripts to python. All the web requests can run sequentially.
Converting was kind of a line by line task.

Good for you, Ben.
I don't know Python at all, but I ight go the Powershell way if I find out how that {auth} part works ...

Jingo

Quote from: Carlo Didier on November 21, 2017, 09:49:06 PM
Quote from: Jingo on November 21, 2017, 09:16:10 PMgive yourself some time.
Well, the scripting engine in IMatch is supposed to make life easier, not more complicated, right? To be able to easily do things without having a university degree in programming.
Having a very (!) simple task to perform, I'm not willing to invest a relatively gigantic amount of time to get it running again.

And even in the most modern programming languages you can still code linear tasks linearly, as long as you don't introduce asynchronous functions (for which there is absolutely no need in the case of linear tasks).

Where is that old KISS ("Keep It Simple, Stupid!") principle?

IMatch apps are displayed and made for BROWSER viewing.. .the app panel itself is a Chromium webapp... this makes using JS, AJAX, etc possible and makes extending IM a powerful option.   Pretty sure that most users find IMatch does 99.5% of the tasks natively without the need for apps (I get this from the slow trickle of app sharing/app requests in the forum)... its only folks that have specific workflows that they are used to and want to continue using where apps can extend things.  In any event... I for one am very happy to have the option and welcome the ability to further develop apps as needed.

Carlo Didier

Yes, the scripting possibility was one of the main factors, many years ago, that turned my decision to IMatch.
But I have absolutely no use for web-based anything and yet I have to live with all the drawbacks that come with it (because in my case there is not a single advantage to it).

Mario

You will have to live with the fact that IMatch has moved on.

Both IMWS as the server product and IMatch as the desktop product now share the same modern programming environment.
You can write apps which work the same with a local IMatch installation and an IMWS server running somewhere on your network. No difference.

A wide choice of modern programming languages, great free tools, powerful debuggers, all for you to pick from.
If you don't like JavaScript, don't use it. Take Python or PowerShell, C#, VB.NET, Go, Java, Koitlin, whatever you fancy. IMWS is agnostic to the programming language you use to access it.

I will utilize the new technology to the max to add new exciting stuff to IMatch.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

ben

QuoteGood for you, Ben.
I don't know Python at all, but I ight go the Powershell way if I find out how that {auth} part works ...

Wasn't meant to sound mean.
Just wanted to point out that there are other options you could try.
And a simple IMatch python script is very similar to the way of scripting you were used to with basic.
O

jch2103

Quote from: Jingo on November 22, 2017, 01:38:14 PM
Pretty sure that most users find IMatch does 99.5% of the tasks natively without the need for apps (I get this from the slow trickle of app sharing/app requests in the forum)... its only folks that have specific workflows that they are used to and want to continue using where apps can extend things.

Exactly. I'm one of those who find IMatch does 99.5% of tasks natively, so haven't felt the need to create any apps. However, I do appreciate the extra opportunities that aps (written by Mario and also others) present!
John

David_H

Quote from: Mario on November 22, 2017, 02:07:27 PM
You will have to live with the fact that IMatch has moved on.

I will utilize the new technology to the max to add new exciting stuff to IMatch.

Mario, doesn't the chrome engine used in IMatch support async/await in its javascript ? If so, wouldn't this be a simple and easy to understand solution for everyone...

Converting the sample 'new' app to async leads me to believe that it works...
Replace the script block with the following :


async function LoadIMatchAppInfo() {

        let response = await IMatch.appInfo({
                        instanceid : IMatch.instanceId()
                    });

                        // When we land here, IMatch has replied.
                        // We update the <h1> and the <p> above with data about this app.

                        $('#app-name').text(response.app.localName);

                        $('#info').html('Folder: <code>' + response.app.folder + '</strong>');

                        // TIP: Uncomment this to see the entire IMatch response, with
                        //      all the data about your app.
            $('#info').append('<br/><br/><pre>' + JSON.stringify(response,null,2) + '</pre>' );
        }

            $(document).ready(function () {
                // TODO: Add your JavaScript in this function.
                //       If this function is called, the HTML is loaded and ready.
                //       You can now run scripts or manipulate HTML contents.


                // EXAMPLE:
                //          We call IMatch (endpoint: imatch/apps/info) to get information
                //          about this app. Then we update the <h1> and <p> tag above
                //          from the results.

                LoadIMatchAppInfo();


                });
                // END EXAMPLE


So, in the document onready, we will call LoadIMatchAppInfo(). So far, so good.

This function is declared as async - so the browser should understand its going to have something special in it (take out the async and watch it not work).

Important bit coming up; we now do:

let response = await IMatch.appInfo({
                        instanceid : IMatch.instanceId()
                    });


Because we're in an async function, the promise that IMatch.appInfo returns is now awaited, and response gets populated with the answer - and THIS is what I think several people are after. Nice, easy to understand, linear code.

Carlo Didier

Hey David. I'll absolutely try that!
If it works, you're my hero!

thrinn

David,
thanks for this! Again, something learned...
Thorsten
Win 10 / 64, IMatch 2018, IMA

Mario

await is part of an upcoming ECMA standard (JavaScript version). It is still considered experimental but most browsers support it, more or less (including Chromium used in IMatch).

let bla = await Promise...

is principally the same as

Promise.then(bla => {
  // Completed, do next-
});

except that you also need to wrap the await in a try ... catch block because it throws an exception if the Promise is not fulfilled/rejected. If you don't handle the reject in a catch, the script will be aborted by the JavaScript runtime.

Using await has some advantages in situations but is basically syntactic sugar in others.
It has the advantage that it stops the async function from within it is used to stop dead and to return only when the Promise has been fulfilled/rejected.

See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await

It depend on your code if this is a benefit or a curse.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

Carlo Didier

Quote from: Mario on November 23, 2017, 08:52:36 AM
let bla = await Promise...

is principally the same as

Promise.then(bla => {
  // Completed, do next-
});

yes, but
let a = await Promise_1...
let b = await Promise_2...
let c = await Promise_3...
let d = something using a, b and c

is much better than
Promise_1.then(a => {
    Promise_2.then(b => {
        Promise_3.then(c => {
            d = ...
        });
    });
});


Now imagine that with more than 3 nesting levels!

Anyway, it doesn't seem to work. I tried
let response = await IMatch.appInfo({
    instanceid : IMatch.instanceId()
});

and got
QuoteExpected ';'
in the first line.

Mario

#37
I never needed 3 nesting levels so I cannot offer advise.
I will consider using await when it becomes an official part of the standard. For now, I also need to support older browsers. And I don't have issues with asynchronous processing so I don't need to find ways to work around them.

Please see MDN for usage instruction for await and other JavaScript tutorials.
-- Mario
IMatch Developer
Forum Administrator
http://www.photools.com  -  Contact & Support - Follow me on 𝕏 - Like photools.com on Facebook

thrinn

#38
Quote from: Carlo Didier on November 24, 2017, 05:48:56 PM
Anyway, it doesn't seem to work. I tried
let response = await IMatch.appInfo({
    instanceid : IMatch.instanceId()
});

and got
QuoteExpected ';'
in the first line.
You can only use await inside an async function (as stated at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await). See also https://hackernoon.com/6-reasons-why-javascripts-async-await-blows-promises-away-tutorial-c7ec10518dd9

Try, for example:

        $(document).ready(function () {
            // This only DEFINES the async function!
            let myAsyncFunc =
                async () => {
                    await IMatch.appInfo({
                        instanceid: IMatch.instanceId()
                    }).then(response => {
                        console.log("Inside the THEN part");
                        $('#app-name').text(response.app.localName);
                        $('#info').html('Folder: <code>' + response.app.folder + '</strong>');
                    });
                    console.log("After the THEN part");
                };

            // Now call the function
            console.log("Before the function call");
            myAsyncFunc();
            console.log("After the function call");
        });


You will get the following output, meaning that "After the THEN part" is really executed only after the appInfo call has finished. Please note that the log call is NOT inside the then part. Note also that the call to the wrapper function myAsyncFunc is still executed asynchronously.
Before the function call
After the function call
Inside the THEN part
After the THEN part

Now remove the await and look at the output again. Note that the order of the messages differs.
Before the function call
After the THEN part
After the function call
Inside the THEN part


Maybe this example can help you, but it is important to read the docs on async/await to understand what is going on.
Thorsten
Win 10 / 64, IMatch 2018, IMA

Carlo Didier

Quote from: thrinn on November 24, 2017, 06:44:28 PM
Maybe this example can help you, but it is important to read the docs on async/await to understand what is going on.

Yes, this helps. I didn't understand the syntax (not from your first example and not from the links you provided), because I still don't understand much of these concepts. The docs are probably fine, but only if you have already some solid base knowledge about all this which I don't have. One of the reasons I get so frustrated with all this. People want to help and give me links to documentations that are basically chinese for me ... they mostly cover rather abstract theory whereas I better understand real working examples. Like, I didn't know what the "let" exactly signifies ... sounds basic for someone with a solid knowledge in javascript, but not for me.

sinus

Quote from: Carlo Didier on November 24, 2017, 08:55:12 PM
Quote from: thrinn on November 24, 2017, 06:44:28 PM
Maybe this example can help you, but it is important to read the docs on async/await to understand what is going on.

Yes, this helps. I didn't understand the syntax (not from your first example and not from the links you provided), because I still don't understand much of these concepts. The docs are probably fine, but only if you have already some solid base knowledge about all this which I don't have. One of the reasons I get so frustrated with all this. People want to help and give me links to documentations that are basically chinese for me ... they mostly cover rather abstract theory whereas I better understand real working examples. Like, I didn't know what the "let" exactly signifies ... sounds basic for someone with a solid knowledge in javascript, but not for me.

I can fully understand you, Carlo.
I can underwrite every word. Specialy this sentence of you:

QuoteOne of the reasons I get so frustrated with all this. People want to help and give me links to documentations that are basically chinese for me ... they mostly cover rather abstract theory whereas I better understand real working examples.

is really true. I also wanted to try it myself. I had also this feeling, people here helped a lot, but on a level, what was for them, I guess, very basic but for me too high to understand.
And if these very nice and helpful people does at the end write basically the script for me, then I was happy but of course had also a bad, ashamed feeling.

But, Carlo, I think, you make a lot of progress, you ask or do things, what are for me chinese, suomi and arabic together.  ;D 8)

So, I think, finally you make progress!  :D
Best wishes from Switzerland! :-)
Markus

Carlo Didier

Quote from: sinus on November 25, 2017, 09:00:54 AM
So, I think, finally you make progress!  :D
I do, Markus! The obstacles into which I bump are getting smaller, but also more subtle and difficult to surmount ...