如何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。 所以你的htmlundefined如错误中所示。

有问题的部分是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编程