为什么这个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个不同的项目进行测试的事实,我在复制/粘贴时混合了文件。
答案 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
解析。因此,您的undefined
为html
,如错误中所示。
有问题的部分是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.body
或Scraper.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之上的语法糖,使它看起来更像是同步代码。
另见: