【问题标题】:Nodejs Promise not resolving/no data returnedNodejs Promise 未解决/未返回数据
【发布时间】:2018-11-11 01:39:55
【问题描述】:

我有一个 promise 函数,它发出两次请求调用并在第二次调用完成后解析。第二次解析调用也依赖于第一次调用的数据。但是在 then 函数中,我得到了变量返回的 null 。任何帮助将不胜感激。

编辑:secResp.body 有正确的数据,它不为空

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);
            });
        });
    });
}

【问题讨论】:

  • 听起来secResp.bodyparticipants 属性是null
  • 添加一个 'retiurn' ..... return getPlayersInMatch(req.params.name).then ....
  • @RobertRowntree - 这如何影响participants 的值导致.then(function(participants)
  • this is an array - 什么是数组? JSON.parse(secResp.body)?如果是这样,那么它永远不会有.participants 属性,因为数组没有。虽然您可以将任何您喜欢的属性添加到数组中,但由于数组是由 JSON.parse“创建”的,因此它永远不会有自定义属性
  • 调试步骤 1 ... console.log(secResp.body) - 将输出添加到问题

标签: javascript node.js promise request


【解决方案1】:

我为request-promise 重写了您的代码。我发现您的代码的主要问题是它太复杂了。简化事情可以更容易地发现你做错了什么。

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 }
}

【讨论】:

  • 谢谢,我切换到使用请求承诺,它似乎工作。
【解决方案2】:
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);
            });
        });
    });
}

试试看。

一,你应该返回请求结果或对象。 二,你应该使用异步等待,因为它不会等待异步回调中的请求数据。

【讨论】:

  • you shoule return request resultyou should use async await 不同意 - 因为您使用它来等待承诺执行器中的承诺,这绝对没有原始代码有意义 - 因为 request.get 不返回保证,await 绝对没有意义
【解决方案3】:

在您的代码中,很难找出哪个步骤出错。

我认为最好像这样包装请求模块:

/**
 * 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:
    • 参数
      • 标签:显示你定义的请求,例如:'first connection'
      • req_opt:请求选项
      • interesting_resp:你感兴趣的关键

注意:在 req_wrap 中,如果在响应中找不到 interesting_resp 中的键(未定义或为空),该函数将拒绝。有必要检查您请求的服务器规格!

你可以重写你的代码:

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)
        })
    });
}

现在检查哪个步骤错误更清楚了。

【讨论】:

    猜你喜欢
    • 2017-10-24
    • 2020-04-11
    • 2021-06-03
    • 2021-12-28
    • 2018-02-06
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    • 2019-03-24
    相关资源
    最近更新 更多