异步函数永不返回
问题描述:
我使用节点版本7.6.0来尝试本地异步并等待功能。异步函数永不返回
我想弄清楚为什么我的异步调用悬挂从未真正解决。
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模块中成功
答
最可能的原因是,你是不是受凉无极错误。我发现它有助于避免try
-catch
,但除了*调用方法外,如果方法可能是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的方法,然后总是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;
}
一般情况下,我觉得这是最好的做法是:
- 保持明确的承诺低级别 - 为您的
rest
和redis
回调设置Promise
包装功能。 - 请确保您的承诺
reject
与new Error
出现问题时。如果一个Promise
不是resolve
而不是reject
那么你的代码停在那里。 - 这些承诺包装的一个每次调用应该有
await
-
try
-catch
右顶部 - 只要每隔Promise
是await
-ed其中任何一方抛出的任何错误都将在*结束catch
大多数问题要么是:
- 你有一个
Promise
能不能resolve
或reject
。 - 您可以拨打
async function
或Promise
而不需要await
。
您是否尝试在您尝试“等待”的所有功能上放置“异步”?因此,尝试在“新承诺”之前添加“等待”。 – Gilsdav
@Gilsdav - 你不'回到等待新的Promise' - async/await是Promises的语法糖 –
显示其他'console.log'消息中的哪一个?你的逻辑听起来好像 –