我想将下面的 callEndPointWrapper 转换为返回 Promise 而不是回调。
我已经使用以下代码进行了测试,但是等待 callEndpointWrapper() 的 Promise 请求超时。
我错过了下面的任何东西吗?
(在调试时,我看到请求在等待 Promise 时在下面的代码行超时:
返回(函数调用端点(回调):任何{
回调:
function callEndPointWrapper(): any {
return function callEndpoint(callback) {
try {
// gRPC call
client[methodName](req, options, callback);
}
catch (err) {
callback(err);
}
};
}
const result = yield callEndpointWrapper();
// I get the correct result from callback above (both on success or error)
promise :
function callEndPointWrapper(): Promise<any> {
return new Promise( (resolve, reject) => {
return (function callEndpoint(callback): any {
try {
// gRPC call
resolve(client[methodName](req, options, callback));
} catch (err) {
reject(callback(err));
}
});
});
const result = await callEndpointWrapper();
// Above request times out.
最佳答案
callEndPointWrapper
的预期结果似乎是一个执行一些异步工作的函数 (callEndPoint
),您可以进一步调用它来执行某些操作。
在您的回调方法中,您正在生成此 callEndPoint
函数。
----> callEndPointWrapper
返回执行异步工作的 callEndPoint
。
另一方面,在基于 promise 的方法中,您试图生成 callEndPoint
的结果,而不是返回 callEndPoint
本身。事实上,callEndPoint
永远不会在 Promise
构造函数中调用。
----> callEndPointWrapper
返回一个永远不会解析的 promise ,并在内部创建一个什么都不做的 callEndPoint
函数,因为它从未被调用。
请务必注意,对 callEndPointWrapper
的单个调用不是异步的。实际的异步部分(假设 client
方法是异步的)发生在 callEndpoint
中,因此基于回调的方法的异步调用类似于:
callEndPointWrapper()(
function callback(responseFromEndpoint) {
// ...
}
)
// or something like
let caller = callEndPointWrapper();
caller(function callback(responseFromEndpoint) {
// ...
});
由此可见,基于 promise 的方法也需要两次调用:
await callEndPointWrapper()(); // call a wrapper which returns a function which returns a promise
回调代码的功能等效(就生成的结果而言)基于 promise 的代码如下:
function callEndPointWrapper(): any {
return function callEndpoint() {
return new Promise((resolve, reject) => {
try {
client[methodName](req, options, (err, result) => {
if (err) return reject(err);
resolve(result);
});
} catch (err) {
// Note: this rejection will only happen on any sync errors
// with the above code, such as trying to invoke a non-existing
// method on the client. This type of error is a programmer error
// rather than an operational error in the system so you should
// consider if such errors should even by caught by your code.
reject(err);
}
});
};
}
但是,这会引出一个问题,如果您没有传递任何配置选项以在 callEndpoint
函数的闭包中可用,那么拥有包装函数的意义何在?
根据您的示例用法,您只需要 callEndpoint
方法即可。
我想到您可能正在使用类似 co
的东西它允许您 yield
函数 (thunks) 并通过回调在内部调用它们。
所以当你这样做的时候
yield callEndpointWrapper()
你实际上是在打电话
yield function callEndpoint(callback) {
// ...
}
然后 co
在幕后为您施展魔法。
这是一个模式 deprecated by co
总体上不建议使用。更不用说需要特定库知识的非常令人困惑(和丑陋的恕我直言)的行为。
要在 co
中使用 promises,您不需要包装器函数。只需 yield
或 await
调用 callEndPoint
的结果(与我上面的 promise 示例中的相同),这将是一个 promise。
yield callEndPoint()
// or
await callEndPoint()
关于javascript - 将回调转换为 Promise,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47226849/