Node.js 未处理的PromisejectionWarning:已调用回调(环回远程方法)
我得到一个错误,上面写着Node.js 未处理的PromisejectionWarning:已调用回调(环回远程方法),node.js,async-await,loopbackjs,es6-promise,Node.js,Async Await,Loopbackjs,Es6 Promise,我得到一个错误,上面写着 (node:27301) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Callback was already called. 根据我对Wait’s和Mozilla描述中拒绝承诺的理解: 如果承诺被拒绝,wait表达式将抛出被拒绝的值 我拒绝回调中围绕我的承诺的错误,如下所示: Airport.nearbyAirports = async
(node:27301) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Callback was already called.
根据我对Wait’s和Mozilla描述中拒绝承诺的理解:
如果承诺被拒绝,wait表达式将抛出被拒绝的值
我拒绝回调中围绕我的承诺的错误,如下所示:
Airport.nearbyAirports = async (location, cb) => {
let airports
try {
airports = await new Promise((resolve, reject) => {
Airport.find({
// code
}, (err, results) => {
if (err)
reject(err) // Reject here
else
resolve(results)
})
})
} catch (err) { // Catch here
cb(err, null)
return
}
if (!airports.empty)
cb(null, airports)
}
我的问题是
为什么它仍然认为我的承诺拒绝未处理?我认为catch
语句应该可以消除这个错误
为什么它会考虑我的回调?我的catch
中有一个return
语句,因此不应该调用这两个语句
如果Airport.find()
抛出异常,则执行将跳转到catch
块,您的承诺将永远不会得到解决或拒绝。也许您需要将其包装在自己的try/catch
中:
Airport.nearbyAirports = async (location, cb) => {
let airports
try {
airports = await new Promise((resolve, reject) => {
try {
Airport.find({
// code
}, (err, results) => {
if (err)
reject(err) // Reject here
else
resolve(results)
})
} catch (err) {
reject(err) // Reject here too
cb(err, null)
}
})
} catch (err) { // Catch here
cb(err, null)
return
}
if (!airports.empty)
cb(null, airports)
}
问题实际上是我的框架(LoopbackJS),而不是我的函数。显然,在撰写本文时,不支持使用承诺:
这意味着我甚至不能在我的函数中使用wait
,因为远程方法将我的函数包装到其他地方,所以async
将始终不被处理。我最终回到了基于承诺的内部代码实现:
Airport.nearbyAirports = (location, cb) => {
const settings = Airport.dataSource.settings
const db = DB(settings)
let airports
NAME_OF_QUERY().then((res) => {
cb(null, res)
}).catch((err) => {
cb(err, null)
})
同样,loopback3通过允许您使用简单的返回来支持这一点
这:
Entry.findFooById = async (id, cb) => {
const result = await Entry.findById(id);
return result;
};
…相当于:
Entry.findFooById = (id, cb) => {
Entry.findById(id)
.then(result => cb(null, result))
.catch(cb);
};
我们使用Loopback 2.31.0,它还支持用于远程方法的异步函数的简单返回。如果将断点放在远程方法的某个位置,并在调用堆栈中跳到其上一级,您将看到它是如何在环回本身()中实现的:
它在这里做什么-它调用您的函数,如果它是异步函数-它将返回一个承诺(retval.then===“function”
将为true
)。在这种情况下,作为承诺,环回将正确处理您的结果。它还为您执行错误检查,因此您不再在代码中尝试/捕获块
因此,在您自己的代码中,您只需要像下面这样使用它:
Airport.nearbyAirports = async (location) => {
let airports = await new Promise((resolve, reject) => {
Airport.find({
// code
}, (err, results) => {
if (err)
reject(err) // Reject here
else
resolve(results)
})
});
if (!airports.empty)
return airports;
}
else {
return {}; // not sure what you would like to return here as it wan not handled in your sample...
}
}
注意,在这里您根本不需要使用回调(cb)。是否有可能您解决并拒绝了没有结果
或错误
?错误
是由第三方API提供的,当我测试它时,我总是得到结果
。否则,我的函数将正确返回。但是,这不再使用await
,这正是我最初的意图。我怎样才能做到这一点?是的。我只是在Promise
的范围内显示了一个新的try/catch
。我已经更新了我的代码,包括了您的所有代码,希望能让它更清晰。相关github问题:
Airport.nearbyAirports = async (location) => {
let airports = await new Promise((resolve, reject) => {
Airport.find({
// code
}, (err, results) => {
if (err)
reject(err) // Reject here
else
resolve(results)
})
});
if (!airports.empty)
return airports;
}
else {
return {}; // not sure what you would like to return here as it wan not handled in your sample...
}
}