asynchronous函数永远不会返回

我使用节点版本7.6.0来尝试本地asynchronous并等待function。

我试图找出为什么我的asynchronous调用悬挂从未真正解决。

NLP模块:

const rest = require('unirest') const Redis = require('ioredis') const redis = new Redis() const Promise = require('bluebird') const nlp = {} nlp.queryCache = function(text) { return new Promise(function(resolve, reject) { redis.get(text, (err, result) => { if (err) { console.log("Error querying Redis: ", err) reject(new Error("Error querying Redis: ", err)) } else { if (result) { let cache = JSON.parse(result) console.log("Found cache in Redis: ", cache) resolve(cache) } else { resolve(null) } } }) }) } nlp.queryService = function(text) { console.log("Querying NLP Service...") return new Promise(function(resolve, reject) { rest.get('http://localhost:9119?q=' + text) .end((response) => { redis.set(text, JSON.stringify(text)) resolve(response.body) }) }) } nlp.query = async function(text) { try { console.log("LET'S TRY REDIS FIRST") let cache = await nlp.queryCache(text) if (cache) { return cache } else { let result = await nlp.queryService(text) console.log("Done Querying NLP service: ", result) return result } } catch (e) { console.log("Problem querying: ", e) } } module.exports = nlp 

模块消费者:

 const modeMenu = require('../ui/service_mode') const nlp = require('../nlp') const sess = require('../session') const onGreetings = async function(req, res, next) { let state = sess.getState(req.from.id) if (state === 'GREET') { let log = { middleware: "onGreetings" } console.log(log) let result = await nlp.query(req.text) console.log("XXXXXXXX: ", result) res.send({reply_id: req.from.id, message: msg}) } else { console.log("This query is not not normal text from user, calling next()") next() } }; module.exports = onGreetings; 

我无法获得代码继续执行以下行:

 console.log("XXXXXXXX: ", result) 

我可以看到查询在NLP模块中是成功的

控制台日志输出

编辑:添加console.log语句到响应正文

控制台输出的实际response.body

日志语句

最有可能的原因是Promise中的一个错误,你没有抓住。 我发现,除了顶级调用方法之外,所有方法都可以避免使用trycatch ,如果一个方法可以await它几乎总是应该的。

在你的情况下,我认为这个问题在这里:

 nlp.queryService = function(text) { console.log("Querying NLP Service...") return new Promise(function(resolve, reject) { rest.get('http://localhost:9119?q=' + text) .end((response) => { redis.set(text, JSON.stringify(text)) // this line is fire and forget resolve(response.body) }) }) } 

具体来说,这行: redis.set(text, JSON.stringify(text)) – 该行正在调用一个函数,没有什么是捕捉任何错误。

解决方法是将所有的Redis方法都包含在promise中,然后一直await它们:

 nlp.setCache = function(key, value) { return new Promise(function(resolve, reject) { redis.set(key, value, (err, result) => { if (err) { reject(new Error("Error saving to Redis: ", err)); } else { resolve(result); } }); }) } nlp.queryService = async function(text) { console.log("Querying NLP Service...") const p = new Promise(function(resolve, reject) { rest.get('http://localhost:9119?q=' + text) .end((response) => { resolve(response.body) }); // This is missing error handling - it should reject(new Error... // for any connection errors or any non-20x response status }); const result = await p; // Now any issue saving to Redis will be passed to any try-catch await nlp.setCache(text, result); return; } 

作为一般规则,我觉得最好的做法是:

  • 保持明确的承诺低级别 – Promise包装函数为您的restrediscallback。
  • 确保您的承诺rejectnew Error出现问题时。 如果Promise没有resolve ,并且不reject那么你的代码就停在那里。
  • 每个对这些诺言包装器之一的调用都应该await
  • try catch最上层 – 只要每一个Promiseawait任何错误都会抛到顶层。

大多数问题将是:

  • 你有一个resolverejectPromise
  • 您可以在不await情况下调用async functionPromise