简体   繁体   中英

Nodejs Promise not resolving/no data returned

I have a promise function that makes two request calls and resolves after the second call is done. The second resolve call also depends on the data from the first call. But in the then function, i am getting null for the variable return. Any help would be appreciated.

Edit: secResp.body has the correct data, it is not null

const express = require('express');
const request = require('request');
const app = express();
const port = process.env.PORT || 5000;

// console.log that your server is up and running
app.listen(port, () => console.log(`Listening on port ${port}`));

app.get('/api/currentMatch/:name', function(req, res, next){
    getPlayersInMatch(req.params.name).then(function(participants){
        //this is null
        console.log(participants);
    }).catch(function (err) {
     console.log(err);
    });
})

function getPlayersInMatch(name){
    return new Promise(function(resolve, reject){
        request.get({
            url: api_url
        }, function(firstErr, firstResp, body){
            if(firstResp.StatusCode != 200){
                reject(firstErr);
            }
            var accountId = JSON.parse(firstResp.body).id;
            request.get({
                url: api_url2 + 'accountId=' + accountId
            }, function(secErr, secResp, body){
                if(secResp.StatusCode != 200){
                    reject(secErr);
                }
                //this is not null, this is an array
                var participants = JSON.parse(secResp.body).participants;
                resolve(participants);
            });
        });
    });
}

I rewrote your code for request-promise . The main issue I found with your code is that it's too complicated. Simplifying things makes it easier to find what you did wrong.

const rp = require('request-promise')
const app = express();
const port = process.env.PORT || 5000;

// console.log that your server is up and running
app.listen(port, () => console.log(`Listening on port ${port}`));

app.get('/api/currentMatch/:name', function(req, res, next){
    getPlayersInMatch(req.params.name)
        .then(console.log)
        .catch(console.error)
})

const getPlayersInMatch = async name => {
    const id = await rp(api_url)
        .then(res => JSON.parse(res.body).id)

    const participants = await rp(api_url2 + 'accountId=' + accountId)
        .then(res => JSON.parse(res.body).participants)

    return { id, participants }
}
function getPlayersInMatch(name){
    return new Promise(async function(resolve, reject){
        return await request.get({
            url: api_url
        }, function(firstErr, firstResp, body){
            if(firstResp.StatusCode != 200){
                reject(firstErr);
            }
            var accountId = JSON.parse(firstResp.body).id;
            request.get({
                url: api_url2 + 'accountId=' + accountId
            }, function(secErr, secResp, body){
                if(secResp.StatusCode != 200){
                    reject(secErr);
                }
                //this is an array
                var participants = JSON.parse(secResp.body).participants;
                resolve(participants);
            });
        });
    });
}

try it.

one, you shoule return request result or object. two, you should use async await because its not wait to request data in async callback.

In your code, it's hard to find out which step gets error.

I think it's better to wrap request module like:

/**
 * Mapping knowing error_code
 * @param {Number} error_code 
 * @param {String} msg 
 */
function error_def(error_code, msg) {
    let status, message;
    switch(error_code){
        case 400:
        case 401:
        case 402:
        case 403:            
        case 1000:
        case 1001:
        case 1002:
        case 1003:
        case 1005:
            status = error_code;
            message = msg;
            break;
        default:
            status =  2000;
            message = 'Undefined Error'
    }
    return {status: status, msg: message};
}

/**
 * Generate error message
 * @param {String} tag
 * @param {Number} error_code
 * @param {String} msg
 */
function gen_error_func(tag = null) {    
    return function(error_code, msg = null) {
        return {tag: tag, error_message: error_def(error_code, msg)}
    }
}

/**
 * Wrap the request and return interesting keys
 * @param {String} tag 
 * @param {Object} req_opt 
 * @param {Array} interesting_resp
 * @return {Object}
 */

function req_wrap(tag = null, req_opt, interesting_resp = null){
    return new Promise((resolve, reject) => {
        let gen_error = gen_error_func(tag)

        if (!req_opt.url) {
            reject(gen_error(1000, 'missing url'));
        }

        let option = {
            url: req_opt.url,
            method: (req_opt.method)? req_opt.method: 'GET',
        }

        request(option, function(error, response, body) {
            if(error) {
                reject(gen_error(1001, error));
                return;
            }

            if (!response) {
                reject(gen_error(1005, 'response is undefine, maybe wrong url!'))
                return;
            }

            if (response.statusCode >= 400) {
                //http level error
                reject(gen_error(response.statusCode, body));
            }else {
                let result = {};
                let body_json;
                try {
                    body_json = JSON.parse(body);
                }catch(e) {
                    reject(gen_error(1002, `Unknow response: ${body}`))
                }
                if (interesting_resp) {
                    interesting_resp.map(key => {
                        if (body_json[key] == undefined) {
                            reject(gen_error(1003, `In ${body_json}, undefined ${key}`))
                            return;
                        }
                        result[key] = body_json[key];
                    })
                }else {
                    result = body_json;
                }
                resolve(result);
            }
        })
    })
}
  • req_wrap:
    • Parameters
      • tag : Showing the request you define, ex: 'first connection'
      • req_opt : request option
      • interesting_resp : the keys what you're interesting

NOTE: In req_wrap, if it cannot find the key in interesting_resp in response (undefined or null) the function will reject. It's necessary to check the server's spec you request!

You can rewrite your code:

function getPlayersInMatch(name){
    return new Promise(function(resolve, reject){
        req_wrap('first_conn', {url: api_url}, ['id']).then(result => {            
            req_wrap('second_conn', {url: api_url2 + 'accountId=' + result.id}, ['participants']).then(result => {
                resolve(result.participants)
            }).catch(error => {
                reject(error)
            })
        }).catch(error => {
            reject(error)
        })
    });
}

Now it's more clear to check which step is wrong.

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