为什么异步/等待在我的代码中不起作用?

时间:2017-07-01 09:00:54

标签: node.js web-scraping async-await undefined

为什么这个async / await不起作用?

我花了一整天时间尝试不同的组合,观看视频和阅读有关async / await的信息,以便在发布此内容之前找到原因无效。

我正在尝试制作一个将在不同端口上运行的第二个nodejs应用程序,我的主应用程序将调用它,以便废弃一些数据并将其保存到db for cache。

它应该做什么: 获取关键字并将其发送到名为 scrapSearch 的方法,此方法创建一个完整的URI链接并将其发送到实际获取网页的方法,并将其返回给第一个调用方。

发生了什么: 在返回结果之前触发初始调用下方的console.log。

控制台输出

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" integrity="sha384-vBWWzlZJ8ea9aCX4pEW3rVHjgjt7zpkNpZk+02D9phzyeVkE+jo0ieGizqPLForn" crossorigin="anonymous"></script>
<nav class="navbar navbar-toggleable-md navbar-inverse bg-inverse fixed-top">
    <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
    </button>
    <a class="navbar-brand" href="#">DCH</a>
    <div class="collapse navbar-collapse" id="navbarSupportedContent">
        <ul class="navbar-nav ml-auto">
            <li class="nav-item">
                <a class="nav-link" href="index.php">Home</a>
            </li>
            <li class="nav-item dropdown">
                <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Feline Diabetes</a>
                <div class="dropdown-menu bg-inverse navbar-inverse">
                    <a class="dropdown-item" href="treatment.php">Treatment</a>
                    <a class="dropdown-item" href="insulin.php">Insulin and Testing</a>
                    <a class="dropdown-item" href="relatedconditions.php">Related Conditions</a>
                </div>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="nutrition.php">Nutrition</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="protocol.php">Protocol</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="links.php">Links</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="http://diabeticcathelp.com/forum" target="_blank">Forum</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="contact.php">Contact Us</a>
            </li>
        </ul>
    </div>
</nav>

app.js

Requesting : https://www.google.ca/?q=mykeyword

  TypeError: Cannot read property 'substr' of undefined
      at /DarkHawk/srv/NodesProjects/_scraper/node_scrapper.js:34:18
      at <anonymous>

废料functions.js

'use strict';
var koa = require('koa');
var fs = require('fs');
var app = new koa();
var Router = require('koa-router');
var router = new Router();

app
  .use(router.routes())
  .use(router.allowedMethods());
app.listen(3002, 'localhost');
router.get('/scraptest', async function(ctx, next) {
    var sfn = require('./scrap-functions.js');
    var scrapFunctions = new sfn();
    var html = await scrapFunctions.scrapSearch("mykeyword");
    console.log(html.substr(0, 20));

    //Normally here I'll be calling my other method to extract content
    let json_extracted = scrapFunctions.exGg('mykeywords', html);
    //Save to db
});

我尝试了很多东西,但我终于放弃了 - 我尝试在每种方法之前设置await / async - 也没用。

为什么这不起作用?

编辑:错误的函数名称基于我创建2个不同的项目进行测试的事实,我在复制/粘贴时混合了文件。

1 个答案:

答案 0 :(得分:1)

您没有从letter = myfont.render("SOME WEIRD TEST TO TRY AND GET THINGS WORKING",0,(0,0,0)) screen.blit(letter,(100,100) 返回任何内容。因为它是一个urlRequest函数,它仍会创建一个承诺,但它会以async解析。因此,您的undefinedhtml,如错误中所示。

有问题的部分是undefined函数,它是一个回调样式函数,但您将其视为一个承诺。对任何不是promise的值使用request将不会执行任何操作(从技术上讲,它会创建一个直接使用值解析的promise,但结果值保持不变)。 <{1}}中的await都不是必需的。

await

您无法从回调中返回值。因为它是异步的,所以在调用回调时你的函数已经完成了。使用回调样式,您可以在回调中完成工作。

但你可以把它变成一个承诺。您必须创建一个新承诺并从urlRequest返回。在承诺内部,您执行异步工作(request(url, function(error, response, html) { if(error) console.error(error); // This return is for the callback function, not the outer function return response; }); )并使用值(响应)解析或拒绝错误。

urlRequest

当发生错误时,您想要从回调中返回,因此不执行其余(成功部分)。我还删除了request关键字,因为它是手动创建一个承诺。

如果您使用的是节点8,则可以使用内置util.promisify宣传Scraper.prototype.urlRequest = function(url) { console.log("Requesting : "+url); return new Promise((resolve, reject) => { request(url, (err, response) => { if (err) { return reject(err); } resolve(response); }); }); }; 功能。

async

这两个版本都将使用request解析并获取您需要使用的const util = require('util'); const request = require('request'); const requestPromise = util.promisify(request); Scraper.prototype.urlRequest = function(url) { console.log("Requesting : " + url); return requestPromise(url); };

response

您仍然需要处理承诺中的错误,包括承诺上的response.bodyScraper.prototype.scrapSearch = async function(keyword) { let url = "https://www.google.ca/?q=" + keyword; let response = await this.urlRequest(url); return response.body; }; 时使用.catch()

在使用try/catch / await时理解promises是绝对必要的,因为它是在promises之上的语法糖,使它看起来更像是同步代码。

另见: