如何asynchronous/等待在我的代码不起作用?
这个asynchronous/等待如何不起作用?
我已经花了整整一天尝试不同的组合,看video和阅读asynchronous/等待,find为什么这不起作用,然后张贴在这里。
我试图做第二个nodejs应用程序将运行在不同的端口,我的主应用程序将调用这个,所以它废弃一些数据,并将其保存到数据库caching。
它应该做什么:取一个关键字并将其发送给一个叫做scrapSearch的方法,这个方法创build一个完整的URI链接,并将其发送给实际获取该网页的方法,并将其返回给第一个调用者。
发生了什么:在返回结果之前触发初始调用下方的console.log。
控制台输出
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>
app.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 });
scrap-functions.js :
'use strict'; var request = require('request'); var cheerio = require('cheerio'); function Scraper() { this.html = ''; //I tried saving html in here but the main script seems to have issues retrieving that this.kw = {}; this.tr = {}; } // Search G0000000gle Scraper.prototype.scrapSearch = async function(keyword) { let url = "https://www.google.ca/?q="+keyword"; let html = await this.urlRequest(url); return html; }; // Get a url'S content Scraper.prototype.urlRequest = async function(url) { console.log("Requesting : "+url); await request(url, await function(error, response, html) { if(error) console.error(error); return response; }); }; module.exports = Scraper;
我尝试了很多东西,但是我终于放弃了 – 在每种方法之前,我都尝试了等待/asynchronous – 也没有工作。
为什么这不起作用?
编辑:错误的函数名称基于我创build了2个不同的项目进行testing,我混合了文件,而复制/粘贴。
你没有从urlRequest
返回任何东西。 因为它是一个async
函数,它仍然会创build一个promise,但是它将会以undefined
来parsing。 所以你的html
是undefined
如错误中所示。
有问题的部分是request
函数,它是一个callback函数,但你把它当作一个承诺。 使用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; });
你不能从callback中返回一个值。 由于它是asynchronous的,你的函数在调用callback的时候已经完成了。 使用callback风格,您可以在callback中完成工作。
但是你可以把它变成一个承诺。 你必须创build一个新的承诺,并从urlRequest
返回。 在承诺内部,您执行asynchronous工作( request
),并使用值(响应)进行parsing,或者拒绝并显示错误。
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); }); }); };
发生错误时,您希望从callback中返回,所以其余(成功的部分)不会被执行。 我也删除了async
关键字,因为它是手动创build一个承诺。
如果您使用的是节点8,则可以使用内置的util.promisify
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
来parsing,并得到您需要使用response.body
的HTML。
Scraper.prototype.scrapSearch = async function(keyword) { let url = "https://www.google.ca/?q=" + keyword; let response = await this.urlRequest(url); return response.body; };
您仍然需要处理承诺中的错误,或者使用.catch()
上的.catch()
,或者在await
时使用try/catch
。
在使用async
/ await
时,理解promise是非常重要的,因为它是承诺之上的语法糖,使它看起来更像同步代码。
也可以看看:
- 在开始使用asynchronous/等待之前了解承诺
- asynchronousfunction – 使承诺友好
- 探索ES6 – 承诺asynchronous编程
- 在Node.js中使用TypeScriptasynchronous等待
- 在节点7.4中使用async / await
- 是否有可能在节点7中使用–harmony_async_await跨asynchronous/等待边界获取堆栈跟踪?
- 无法解决承诺时使用asynchronous与巴贝尔和ES6诺言等待
- 在Nodejs中使用asynchronous等待redis和bluebird
- Node.js最佳实践exception处理 – asynchronous/等待之后
- Intellij Idea警告 – 用aysnc / await“返回的Promise被忽略”
- 在失败之前轮询n次(在两次尝试之间有延迟)
- 在循环中使用async / await