2

I am running a server that is serving a Vue.js app. So if I input http://localhost:9999/ into my browser, the browser gets 4 important files: post.js, get.js, vue.js and the index.HTML with the vue code.

I got a dynamic ordered list to work where each list element has a button to add an element and to remove itself as well as a debug button which outputs some variables to the console.

Now I need to make a get request to my server to get an Array with JSON data that will create some elements in a second ordered list.

I tried the following but nothing works:

//get("http://localhost:9999/text/1", inputData)
//get("http://localhost:9999/text/1").then(inputData)
//inputData = get("http://localhost:9999/text/1")

This is the content of get.js:

//which is correctly included in the vue.js index.HTML
//<script SRC="get.js"> </script>
function get(url, params) {
        // Return a new promise.
        return new Promise(function(resolve, reject) {
            // Do the usual XHR stuff
            var req = new XMLHttpRequest();
            req.open('GET', url, true);
        req.setRequestHeader('Content-type', 'application/json');

            req.onload = function() {
                // This is called even on 404 etc
                // so check the status
                if (req.status == 200) {
                    // Resolve the promise with the response text
                    //resolve(req.response);
                    resolve(JSON.parse(req.response));
            }
            else {
                // Otherwise reject with the status text
                // which will hopefully be a meaningful error
                reject(req.statusText);
            }
        };

        // Handle network errors
        req.onerror = function() {
            reject("Network Error");
        };

        // Make the request
        req.send(params);
    });
}

After the vue.js method block I call

mounted() {
    this.$nextTick(function () {
    var inputData=[]
    //get("http://localhost:9999/text/1", inputData)
    //get("http://localhost:9999/text/1").then(inputData)
    inputData = get("http://localhost:9999/text/1")
    app.vueData = inputData
    console.log(inputData)
    console.log(JSON.stringify(inputData))
    console.log(';)')
    })
}

The Promise has the content but I can't transfer it to the variable.

Promise {<pending>}
__proto__: Promise
catch: ƒ catch()
constructor: ƒ Promise()
finally: ƒ finally()
then: ƒ then()
Symbol(Symbol.toStringTag): "Promise"
__proto__: Object
[[PromiseStatus]]: "resolved"
[[PromiseValue]]: Array(4)
0: {text: "This List"}
1: {text: "was pulled"}
2: {text: "from the"}
3: {text: "server"}
length: 4
__proto__: Array(0)

Since comments get deleted I have to get creative:

@Apal Shah Thanks for this answer. Your code looks way better than the then() solution. I got wind of the culprit before reading your solution by adding a lot of console.log()s

console.log('app.vueData vor app.vueData = inputData: ')
console.log(app.vueData)

app.vueData = inputData

console.log('inputData nach Zuweisung: ')
console.log(inputData)

console.log('JSON.stringify(inputData)')
console.log(JSON.stringify(inputData))

console.log(';)')

Console Output:

get block:                                                                  (index):153
app.vueData vor app.vueData = inputData:                                    (index):156
 [__ob__: Observer]                                                         (index):157
  length: 0
  __ob__: Observer {value: Array(0), dep: Dep, vmCount: 0}
  __proto__: Array
inputData nach Zuweisung:                                                   (index):161
 [__ob__: Observer]                                                         (index):162
  length: 0
  __ob__: Observer {value: Array(0), dep: Dep, vmCount: 0}
  __proto__: Array
 JSON.stringify(inputData)                                                  (index):164
 []                                                                         (index):165
 ;)                                                                         (index):167

 Download the Vue Devtools extension for a better development experience:   vue.js:9049
 https://github.com/vuejs/vue-devtools

 You are running Vue in development mode.                   vue.js:9058
 Make sure to turn on production mode when deploying for production.
 See more tips at https://vuejs.org/guide/deployment.html

 (4) [{…}, {…}, {…}, {…}]                                                   (index):154
  0: {text: "This List"}
  1: {text: "was pulled"}
  2: {text: "from the"}
  3: {text: "server"}
  length: 4
  __proto__: Array(0)

Thanks a bunch going to test it now.

The solution is:

mounted() {
    this.$nextTick(async function () {

        console.log('get block: ')
        console.log('app.vueData vor app.vueData = get() ')
        console.log(app.vueData)

        //Get is a deferred / asynchronous process / operation
        app.vueData = await get("http://localhost:9999/text/1")

        console.log('app.vueData nach Zuweisung: ')
        console.log(app.vueData)

        console.log('JSON.stringify(app.vueData)')
        console.log(JSON.stringify(app.vueData))
        })

        console.log(';)')
}

The caveat was that async had to go in front of function not mounted or this.$nextTick .

vueNoob
  • 51
  • 1
  • 6
  • 1
    have you tried something like `get("http://localhost:9999/text/1").then(inputData => { console.log(inputData) })` ? – Chris Li Jul 17 '19 at 14:45

1 Answers1

0

You have created a Promise which resolves the data after the completion of your HTTP request but your code is not waiting for this promise to resolve.

You can do 2 things:
1. Use .then()
2. Use async/await (I prefer this because it looks clean)

If you want to use async/await,

mounted() {
    this.$nextTick(async function () {
    var inputData=[]
    //get("http://localhost:9999/text/1", inputData)
    //get("http://localhost:9999/text/1").then(inputData)
    inputData = await get("http://localhost:9999/text/1")
    app.vueData = inputData
    console.log(inputData)
    console.log(JSON.stringify(inputData))
    console.log(';)')
    })
}

In this code, you can see that there is async keyword before the function inside this.$nextTick and await keyword before your get method.

If you want to handle the error, you can always use try/catch block.

try {
  inputData = await get("http://localhost:9999/text/1");
} catch (e) {
  console.log(e);
}

If you're a fan of .then(), your mounted method would look something like this,

mounted() {
    this.$nextTick(function () {
    var inputData=[]
    get("http://localhost:9999/text/1").then(inputData => {
      app.vueData = inputData
      console.log(inputData)
      console.log(JSON.stringify(inputData))
    });
    console.log(';)')
    })
}
Apal Shah
  • 680
  • 8
  • 17
  • Thanks have a look at the question again if you are interested because I updated it. :) – vueNoob Jul 18 '19 at 09:26
  • Ohh I didn't see there is a function inside this.$nextTick! I've also updated my answer. But at the end, async/await with try/catch is the best solution which I always use. – Apal Shah Jul 18 '19 at 14:11