将callback转换为Promise
我想转换下面的callEndPointWrapper返回一个Promise而不是callback。 我已经testing了下面的代码,但在等待Promise for callEndpointWrapper()请求超时。 我是否错过了下面的任何东西? (在debugging的时候,我看到请求超出了代码的下面,等待Promise: return (function callEndpoint(callback): any {
回电话:
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)
诺言:
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
),它执行一些asynchronous工作,您可以进一步调用它来执行某些操作。
在您的callback方法中,您正在生成此callEndPoint
函数。
—-> callEndPointWrapper
返回asynchronous工作的callEndPoint
。
另一方面,在您的基于承诺的方法中,您正尝试产生callEndPoint
的结果,而不是返回callEndPoint
本身。 事实上,在Promise
构造函数中从不调用callEndPoint
。
—-> callEndPointWrapper
返回一个承诺,永远不会解决,并在内部创buildcallEndPoint
函数什么都不做,因为它永远不会被调用。
请注意,一次调用callEndPointWrapper
不是asynchronous的。 实际的asynchronous部分(假设client
方法是asynchronous的)发生在callEndpoint
所以对于基于callback的方法的asynchronous调用将是这样的:
callEndPointWrapper()( function callback(responseFromEndpoint) { // ... } ) // or something like let caller = callEndPointWrapper(); caller(function callback(responseFromEndpoint) { // ... });
由此可见,基于承诺的方法还需要两个调用:
await callEndPointWrapper()(); // call a wrapper which returns a function which returns a promise
您的callback代码的基于承诺的代码在function上等效(根据生成的结果)如下:
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
函数的闭包中传递任何configuration选项,这会导致如何使用包装函数?
根据您的示例使用情况,您所需要的只是callEndpoint
方法。
想到你可能会使用类似co
东西,它允许你yield
函数(thunk),并在内部用callback调用它们。
所以,当你这样做
yield callEndpointWrapper()
你实际上正在打电话
yield function callEndpoint(callback) { // ... }
然后co
为你做了一些魔术。
这是一个被co
弃用的模式,总体上不适合使用。 更不用说,这是非常混乱(和丑陋的恕我直言)的行为,需要知识的特定图书馆。
要使用co
promise,你不需要包装函数。 只是yield
或await
调用callEndPoint
(与我上面的诺言中的例子相同)的结果,这将是一个承诺。
yield callEndPoint() // or await callEndPoint()