简体   繁体   中英

Javascript Promise: can't get the return value out of my function

I can not get the return object out of my function, so I can reuse it in the next function which should be called by my promise.then() . Struggling with researching, and can not find the solution.

engine.log is basically equivalent to console.log in my application.

firstRequest
    .then( function (result) {
            return secondRequest(result)
        },
        error => engine.log(error)
    )
    .then(
        result => engine.log(result), // result is undefined, need the object here
    )

let firstRequest = new Promise(function(resolve, reject) {
        http.simpleRequest({
            'method': 'GET',
            'url': theUrl,
            'dataType': 'json',
            'timeout': 6000,
        }, function (error, response) {
            if (error) {
                engine.log("Error: " + error)
                reject()
            }

            if (response.statusCode != 200) {
                engine.log("HTTP Error: " + response.status)
                reject()
            }

            myObject = JSON.parse(response.data)
            resolve(myObject)
        })
});

function secondRequest(request) {
    http.simpleRequest({
        'method': 'GET',
        'url': theSecondUrl,
        'dataType': 'json',
        'timeout': 6000,
    }, function (error, response) {
        if (error) {
            engine.log("Error: " + error);
        }

        if (response.statusCode != 200) {
            engine.log("HTTP Error: " + response.status);
        }

        myObject = JSON.parse(response.data)
        return myObject // this is not being returned, to the .then()
    })
}

Javascript promises are asynchronous. Meaning they are resolved in the event loop, if the promise is resolved as soon as your call to .then() callback, then you will get the value in the next function as you expect.

Javascript promises are made asynchronous since typical API calls or database retrieving may involve network delays or any other delays to return the data. Thus the users will see these delays as performance issues. To avoid this kind of effect Javascript event loop is doing its job as running promises asynchronously . Meaning the code after promises is run most probably before it gets resolved or rejected. Therefore your next function will not have the value of first promise when its code is run. In the next iteration or 1+ iterations of the event loop, your promise may get resolved/rejected and then may have populated with the corresponding value.

The solution =>

You should use async await to make any asynchronous code synchronous in javascript.

You could read more about it here. https://javascript.info/async-await

Firstly, I see redundant code, so I would consolidate your requests into a single more generic function. It seems your desire not to do this is you feel you have to pass a 'request' parameter to your second function, but notice that you never use it. Just pass a url in both cases.

In your generic function, which below i'm calling 'makeRequest', be sure to return the promise, or else you'll get undefined. Also, be sure to call resolve on the parsed object, not return ;

Also, I'd use catch for your errors, that way you'll catch it whenever an error occurs, whether it's in the first then or the second one.

This is untested, by the way, but I think the general points are in there.

makeRequest('somewhere')
.then(result => makeRequest('theSecondUrl'))
.then(result => engine.log(result))
.catch(error => engine.log(error));

function makeRequest (url, method, datatype, timeout) {

    return new Promise(function(resolve, reject) {

        http.simpleRequest({
            'method': method || 'GET',
            'url': url,
            'dataType': datatype || 'json',
            'timeout': timeout || 6000,
        }, function (error, response) {

            if (error) {
                engine.log("Error: " + error)
                reject()
            }

            if (response.statusCode != 200) {
                engine.log("HTTP Error: " + response.status)
                reject()
            }

            // use 'let' or else you've made a globally scoped variable
            let parsed = JSON.parse(response.data) 
            resolve(parsed);

        });

    })

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM