-1

In my script I need to make a XMLrequest, get the response from the server (if resolved), parse it and place the parsed result in a variable.

Only later, with this variable I can do lot of stuff.

So basically, I am trying to separate the creation of such parser object from the rest of my code, in order to:

  • place the above process into a function in an external script which I can call whenever I need.
  • not having all my code within a .then() method
  • organize my code into logical files each devoted to a specific task

So I came up with this piece of code (just a sample) to explain my needs. As I am fairly new to asyncronous programming, would it be fine to do like so, given that the response should be very fast to resovle (or to reject) in my case?

If it's ok, I would then put this inside a separate file to be able to import it and call testing() (or whatever the name will be) from anywhere I need.

function delay(input) {
    return new Promise(function(resolve, reject) {
        // some async operation here
        setTimeout(function() {
            // resolve the promise with some value
            resolve(input + 10);
        }, 500);
    });
}

function testing() {delay(5).then(result => {return document.write(result)})};

testing();

EDIT

Ok, so I think I hit the problem thanks to the answer of @DrewReese and the links in the comments.

I am trying to solve this situation: the code above was misleading to understand my point, but I guess tere's no really simple solution. Look at this code (it's basically the same as the one above, except fot the last three lines):

function delay(input) {
    return new Promise(function(resolve, reject) {
        // some async operation here
        setTimeout(function() {
            // resolve the promise with some value
            resolve(input + 10);
        }, 500);
    });
}

function testing() {delay(5).then(result => {return result})};

var test = testing();
document.write(test);

So in this case, I know when I am defining test the output is 'undefined' because the Promise in testing() has not yet resolved.

The problem I'm trying to solve is: is there (if any) a way to define test only when the Promise is resolved without wrapping it in a then() and maybe outputting something different when it's not resolved (like "LOADING...").

I don't know basically if it is possible to check if a variable has a Promise pending and outputting two different values: when it's waiting and when it's resolved/rejected.

Hopefully I was clear enough, otherwise I'll test more and come back with another question if needed.

umbe1987
  • 2,894
  • 6
  • 35
  • 63
  • What's your question? The code works fine. – Barmar Jun 26 '18 at 15:59
  • " would it be fine to do like so". The question means: "Am I missing something really to be aware of or it is totally fine doing so. For instance: is there a better (or completely different) way to do it?" I couldn't find any example which separaets the logic of the retrieving a Promise response and trating its result into two separate files. – umbe1987 Jun 26 '18 at 16:02
  • 2
    There are other ways to do it, like ES6 async function and `await`. – Barmar Jun 26 '18 at 16:03
  • The fact that they're in separate files is completely irrelevant. Once everything is loaded, it doesn't matter where the code came from. – Barmar Jun 26 '18 at 16:03
  • Ok, I am aware of async and await. But I guess (from my ignorant perspective) that eventually you still need to call .then(), am I wrong? – umbe1987 Jun 26 '18 at 16:04
  • Questions about best practices and code organization are not really on-topic here, they're mostly opinion-based. We try to stick to objective questions. – Barmar Jun 26 '18 at 16:04
  • Ok, should I migrate to CodeReview then? If so, would you kindly suggest how to do it? Thanks for the feedback. – umbe1987 Jun 26 '18 at 16:07
  • @Barmar Anyway, if there's nothing to be worried about, I would then assume the answer is as simple as "Yes, it is fine". The question seems legitimate to me, my original aim was not to ask for suggestions, but for possible drawbacks of doing this. – umbe1987 Jun 26 '18 at 16:10
  • 1
    The devil is in the details. Your little snippet is fine, it's harder to know whether your real application will work properly without seeing it. If you set a variable in an async function, you need to ensure that you don't try to use it until it has actually been set. See https://stackoverflow.com/questions/14220321/how-to-return-the-response-from-an-asynchronous-call and https://stackoverflow.com/questions/23667086/why-is-my-variable-undefined-after-i-modify-it-inside-of-a-function-asynchron?newsletter=1&nlcode=97716%7c4ba7 – Barmar Jun 26 '18 at 16:15
  • @Barmar I edited my question to hopefully explain my point better. It's been difficult to write it, I hope now it's clear. – umbe1987 Jun 27 '18 at 07:55
  • 1
    If I understand correctly, it seems you have two questions: (1) How to not get an undefined return value from a Promise, and (2) Is there a way to test the pending status of a running Promise. The answer to the first is to do as @Barmar has suggested and my example of... use async/await. For the second question I just googled it and it seems there are ways/examples of checking the pending status of a Promise, but they all seem very anti-pattern for Promises... just wait for it to resolve and "callback", or reject... there's not a strong argument for trying to monitor the status of a Promise. – Drew Reese Jun 27 '18 at 17:54

1 Answers1

1

The whole point of promises (promise chains) is to escape from "nesting hell" by flattening your "chain", so yes, when your promise chain is resolving blocks of code, it is returning a promise which is then-able. I hope this helps illustrate:

someAsyncHttpRequest(parameter) // <- Returns Promise
    .then(result => {
        // do something with result data, i.e. extract response data, 
        //  mutate it, save it, do something else based on value
        ...
        // You can even return a Promise
        return Promise.resolve(mutatedData);
    })
    .then(newData => {  // <- mutadedData passed as parameter
        // do new stuff with new data, etc... even reject
        let rejectData = processNewData(newData);
        return Promise.reject(rejectData);
    })
    .catch(err => {
        console.log('Any caught promise rejection no matter where it came from:', err);
    })
    .finally(() => {// You can even run this code no matter what});

If you need to use any variable values you set within the chain, then you need to make the outer function async and await on the resolution of the promise chain:

asyncFunction = async (parameter) => {
    let asyncValue;

    await someAsyncHttpRequest(parameter)
        .then(result => {
            ...
            asyncValue = someValue;
            ...
        });
    // safe to use asyncValue now
};

So for you:

function delay(input) {
    return new Promise(function(resolve, reject) {
        // some async operation here
        setTimeout(function() {
            // resolve the promise with some value
            resolve(input + 10);
        }, 500);
    });
}

**async** function testing() { // Declare this an asynchronous function
    let value = **await** delay(5); // Now you can await the resolution of the Promise
    console.log(value); // Outputs resolved value 15!
    return value; // Just returns resolved Promise
}

var test = testing();

console.log(test); 
/** Outputs the Promise!
   Promise {<pending>}
     __proto__:Promise
     [[PromiseStatus]]:"resolved"
     [[PromiseValue]]:15
*/

test.then(console.log)); // Outputs returned resolved value, 15
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • It's weird to mix await with `then` like you last example. Why not just assign `asyncValue` with the result of `someAsyncHttpRequest`? – Mark Jun 26 '18 at 17:53
  • That's what this code does. `someAsyncHttpRequest` returns a promise containing the result you want to save. Promises use callbacks, so without the await, javascript will happily process the request and chug along... with the await it pauses the execution of the function and waits for the resolution of the promise chain first, before continuing. – Drew Reese Jun 26 '18 at 18:58
  • I don't think I was clear, sorry. My point was this is more idiomatic of aync/await: `let asyncValue = await someAsyncHttpRequest(parameter)`. There's no need for the `then()` – Mark Jun 26 '18 at 19:02
  • Oh, I see what you mean. I was merely trying to demonstrate setting variables from within the chain, so using the passed result is a little oversimplified. – Drew Reese Jun 27 '18 at 05:39