简体   繁体   English

我自己的 function 中的 Node.js 请求模块出现问题

[英]Problem with Node.js Request module inside my own function

I have this code:我有这个代码:

const request = require('request');

let url = "https://api.warframe.market/v1/items";

let options = {json: true};
let item_urls;
//const response;
request(url, options, (error, res, body) => {
    if (error) {
        return  console.log(error)
    };

    if (!error && res.statusCode == 200) {
        console.log(body);
        item_urls = body.payload.items;

    };
});

It works fine and returns the JSON to the variable item_urls .它工作正常并将 JSON 返回到变量item_urls

I then tried to wrap my own function around it like so:然后我尝试将我自己的 function 包裹在它周围,如下所示:

const request = require('request');

let url = "https://api.warframe.market/v1/items";

let options = {json: true};
let item_urls;
//const response;

function getitems(){
request(url, options, (error, res, body) => {
    if (error) {
        return  console.log(error)
    };

    if (!error && res.statusCode == 200) {
        console.log(body);
        item_urls= body.payload.items;

    };
});
};
getitems()

But it doesn't work, item_urls ends up being undefined.但它不起作用, item_urls最终未定义。 The code is identical except for being wrapped inside my function.除了包裹在我的 function 中之外,代码是相同的。 In case you are wondering why I want to it wrapped inside a function - I need to pass a parameter to it but I've removed this logic for simplicity and to demonstrate the issue.如果您想知道为什么我要将它包裹在 function 中 - 我需要向它传递一个参数,但为了简单起见,我已经删除了这个逻辑并演示了这个问题。

Thanks,谢谢,

EDIT: Additional details I forgot to mention sorry.编辑:其他细节我忘了说抱歉。

So I am running this code directly line by line in my IDE and sending the lines to the node REPL so that I can test code line by line.因此,我在 IDE 中直接逐行运行此代码,并将这些行发送到节点 REPL,以便我可以逐行测试代码。 If we look at the first block of code:如果我们看一下第一段代码:

I highlight it all and run it.我突出显示并运行它。 Since request is async, I wait for it to complete first, I know it's completed because the callback function outputs the body to the console, so I wait until I see a load of data get printed to the console, this is how I verify the command completed successfully.由于请求是异步的,我先等待它完成,我知道它已经完成,因为回调 function 将主体输出到控制台,所以我等到看到大量数据打印到控制台,这就是我验证的方式命令成功完成。 Straight after the line of code which outputs the body to the console it then dumps the body into my variable.在将正文输出到控制台的代码行之后,它将正文转储到我的变量中。 To confirm this has worked I then type item_urls at the REPL terminal itself and can see the output.为了确认这是否有效,我然后在 REPL 终端本身输入item_urls并可以看到 output。

With the second block of code, I open a new REPL so everything is clean.使用第二个代码块,我打开了一个新的 REPL,所以一切都很干净。 I then execute all the lines of code again and wait... What I am expecting is for the request async call to take a few seconds to complete like the first code block.然后我再次执行所有代码行并等待......我期望的是请求异步调用需要几秒钟才能完成,就像第一个代码块一样。 However, nothing get's outputted to the console.但是,没有任何东西输出到控制台。 I wait up to 30 secs (the previous block of code only took around 5 secs) then I type item_urls at the REPL terminal again and it says undefined.我最多等待 30 秒(前一个代码块只花了大约 5 秒)然后我再次在 REPL 终端输入item_urls并显示未定义。

I am convinced it has something to do with the async and callback nature but I can't figure out what.我确信它与异步和回调性质有关,但我不知道是什么。

You have to use item_urls INSIDE the callback in which you first get its value.您必须在第一次获取其值的回调中使用item_urls The only way you can use that value is to use it right there in the callback itself or in a function you call from there and pass it the value.您可以使用该值的唯一方法是在回调本身中使用它,或者在您从那里调用的 function 中使用它并将值传递给它。

The issue is that request() is asynchronous and non-blocking.问题是request()是异步且非阻塞的。 That means that you execute request() , it starts the operation and then it returns and goes right on executing more code (including the code where you try to use item_urls ).这意味着您执行request() ,它开始操作,然后返回并继续执行更多代码(包括您尝试使用item_urls的代码)。 But, at that point, the callback has not yet been called so it's still undefined .但是,此时尚未调用回调,因此它仍然是undefined

In the end, the ONLY place that you know item_urls has a value is inside that callback.最后,您知道item_urls具有值的唯一地方是在该回调中。 So, any code that uses that value needs to go inside that callback or get called from inside that callback.因此,任何使用该值的代码都需要在该回调内 go 或从该回调内调用。 That's how asynchronous programming works in node.js.这就是 node.js 中异步编程的工作原理。

So, it would need to look like this:所以,它需要看起来像这样:

function getitems(){

    request(url, options, (error, res, body) => {
        if (error) {
            return  console.log(error)
        }

        if (!error && res.statusCode == 200) {
            console.log(body);
            // use body.payload.items directly here
            // or call some function here and pass it the value
            // Do not assign it to some higher scoped variable and
            // expect to use it elsewhere.  Can't do that.
        }
    });
}

getitems()

If you want to get the value outside of getitems, then you need to use either a callback, and event or a promise to communicate the asynchronous retrieved value outside of getitems() .如果要在 getitems 之外获取值,则需要使用回调和事件或 promise 在getitems()之外传达异步检索到的值。 You can see a full discussion of why you can't just return the value from getitems() here in this highly popular answer: How do I return the response from an asynchronous call .您可以在这个非常受欢迎的答案中看到关于为什么不能只从getitems()返回值的完整讨论: 如何从异步调用返回响应


I don't know what you think doesn't work about the 2nd code block where the code is in a function.我不知道您认为代码位于 function 中的第二个代码块有何作用。 I just put this into a file by itself and executed it and it works just fine.我只是将它自己放入一个文件并执行它,它工作得很好。 So, if you remove item_urls from the equation and you use the result inside the callback like I suggested above, it all works just fine, even in the second code block.因此,如果您从等式中删除item_urls并像我上面建议的那样在回调中使用结果,那么即使在第二个代码块中也一切正常。

Here's the exact program I just ran:这是我刚刚运行的确切程序:

const request = require('request');

let url = "https://api.warframe.market/v1/items";

let options = {
    json: true
};
function getitems() {
    request(url, options, (error, res, body) => {
        if (error) {
            return console.log(error);
        }

        if (res.statusCode === 200) {
            console.log(body.payload.items);
        }
    });
}
getitems()

This code works.此代码有效。 It gives me output like this:它给了我这样的 output :

[
  {
    id: '5835a4564b0377e226bdc360',
    url_name: 'axi_c1_intact',
    thumb: 'icons/en/thumbs/Axi_C1_Intact.99413ebefc5b87d57d9e5314265b56de.128x128.png',
    item_name: 'Axi C1 Intact'
  },
  {
    id: '5835a4dd4b0377e226bdc380',
    url_name: 'meso_s3_intact',
    thumb: 'icons/en/thumbs/Meso_S3_Intact.caee59471a7b06ca040f2d257083e008.128x128.png',
    item_name: 'Meso S3 Intact'
  },
  {
    id: '58d8f31c11efe42a5e523215',
    url_name: 'lith_n2_exceptional',
    thumb: 'icons/en/thumbs/Lith_N2_Exceptional.b82a140ba17908be7226fddcecd7bf62.128x128.png',
    item_name: 'Lith N2 Exceptional'
  },
  {
    id: '5936dd6916efa3a742b15f48',
    url_name: 'lith_n3_exceptional',
    thumb: 'icons/en/thumbs/Lith_N3_Exceptional.b82a140ba17908be7226fddcecd7bf62.128x128.png',
    item_name: 'Lith N3 Exceptional'
  },
  {
    id: '5835a4404b0377e226bdc358',
    url_name: 'neo_v4_intact',
    thumb: 'icons/en/thumbs/Neo_V4_Intact.e0e38afae723757487927845b35a81d2.128x128.png',
    item_name: 'Neo V4 Intact'
  },

  .... a whole bunch more items

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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