我想转换下面的callEndPointWrapper来返回Promise而不是回调。
我已经使用下面的代码进行了测试,但是等待Promise for callEndpointWrapper()请求超时。
我错过了下面的任何东西吗?
(在调试时,我在等待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.
答案 0 :(得分:1)
callEndPointWrapper
的期望结果似乎是一个函数(callEndPoint
),它执行一些异步工作,您可以进一步调用它来执行某些操作。
在回调方法中,您正在生成此callEndPoint
函数。
----&GT; callEndPointWrapper
返回执行异步工作的callEndPoint
。
另一方面,在基于承诺的方法中,您试图生成callEndPoint
的结果而不是返回callEndPoint
本身。实际上,callEndPoint
永远不会在Promise
构造函数中调用callEndPointWrapper
。
----&GT; callEndPoint
返回一个永不解析的promise,并在内部创建不执行任何操作的callEndPointWrapper
函数,因为它从未被调用过。
值得注意的是,对client
的单次调用并非异步。实际的异步部分(假设callEndpoint
方法是异步的)发生在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
由此可见,基于承诺的方法也需要两次调用:
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
函数的闭包中可用,那么这就产生了一个问题:如何设置包装函数呢?
根据您的示例用法,您只需要yield
方法。
我想到你可能正在使用类似co
的东西,它允许你yield callEndpointWrapper()
函数(thunks)并在内部通过回调调用它们。
所以当你这样做时
yield function callEndpoint(callback) {
// ...
}
你实际上是在打电话
co
然后co
为你做了一些魔术。
这是一种deprecated by co
的模式,总体上不明智。更不用说它需要知道特定的库,这是非常混乱(和丑陋的恕我直言)行为。
要使用yield
的承诺,您不需要包装函数。只需await
或callEndPoint
调用yield callEndPoint()
// or
await callEndPoint()
的结果(与我上面的承诺示例相同),这将是一个承诺。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:id="@+id/shoppingDetailsScrollView"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#aabbcc"
android:fillViewport="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<android.support.constraint.ConstraintLayout
android:id="@+id/contentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:background="@color/place_holder_color">
</android.support.constraint.ConstraintLayout>
</ScrollView>
</android.support.constraint.ConstraintLayout>