Closed AllenDang closed 6 years ago
Such things better ask on sciter.com
https://github.com/c-smile/sciter-sdk/issues/83
Wait, you are stating that it does not work only with Go.
Than it belongs here.
I actually filed another issue here...
Than it belongs here.
Nah, it doesn't. You just doing it wrong.
First of all, documentation:
await
)The await
operator works with promise
s and only with promise
s while a view.NativeFunction
isn't a promise, of course.
To make your code work use the following:
async function asyncNative(self) {
// create a `promise` object with our own callback
var p = promise(function(resolve, reject) {
debug: "promise start";
try {
// call our native function here
var res = view.native_func();
debug: "promise ready";
// and pass the result back to the `await` waiter
resolve(res);
}
catch(e) {
debug alert: "promise error" e.message e.data;
// catch an error and pass it to the `await` caller
reject(e);
}
// nothing to see here, really
debug: "promise end";
});
debug: "request";
// the following is wrong since native functions aren't promises-like objects:
// var res = await view.asyncNative();
// use this instead:
var res = await p;
// fullfill the UI:
debug: "result" res;
$(output).value = res;
// and finally restore the button's state back:
self.state.disabled = false;
}
And call it:
$(#nativeasync) << event click {
// prepare the UI
this.state.disabled = true;
// call our async function
asyncNative(this);
// the following is wrong because
// an async function returns **immediately**;
// use callback instead
// this.state.disabled = false;
}
You really save my life here!
No, it still doesn't work...
go side
func sleep() {
time.Sleep(time.Second * 4)
}
tiscript side
async function asyncSleep() {
var p = promise(function(resolve, reject) {
try {
var res = view.sleep();
resolve(res);
} catch(e) {
reject(e);
}
});
$(#btnGo).state.disabled = true;
var result = await p;
$(#btnGo).state.disabled = false;
}
When I call asyncSleep() the main thread still be blocked.
Also it can be simplified to:
async function asyncNative() {
var p = promise(function (on_ok, on_fail) {
view.async_func(on_ok, on_fail);
});
return await p;
}
w.defineFunction("async_func", func(args... *sciter.Value) *sciter.Value {
on_ok := args[0]
on_fail := args[1]
// in form of `script.Invoke(this, "stacktrace", args...)`
on_ok.Invoke(sciter.NullValue(), "[async_func]", sciter.NewValue("OK"))
})
When I call asyncSleep() the main thread still be blocked.
What do you mean by "main thread"?
UI is not responding.
How about doing blocking operations in a goroutine and calling promise when done?
I thought about using goroutine and callback when it's done. Side effect is this breaks the async/await pattern sciter has.
Why does this break the pattern?
async function asyncNative() {
var p = promise();
view.set_promise(p);
// await
var res = await p;
// use result
$(output).value = String.printf("ok: %V", res);
}
@sciter.script(convert=False)
def set_promise(self, oath):
def thread_func(oath):
import time
time.sleep(2)
oath(True, ["OK"])
import threading
t = threading.Thread(target=thread_func, args=(oath,))
t.start()
pass
It is in Python but you've got the point: I create a promise
, pass it to the native code which creates a new thread and does some sleepy work. Eventually the promise is fulfilled by result.
Note the array in oath(True, params)
because (from the docs):
call it as
prom(true, params)
. Where the params is an array of values that will be applied toonFulfilled
callback functions registered by.then()
method.
En, you got the point. I think you are right.
It seems I cannot invoke the promise object at go side.
tiscript
var p = promise();
view.longOp(p);
var result = await p;
go side
func waitHere(p *sciter.Value) {
time.Sleep(time.Second * 5)
p.Invoke(sciter.NullValue(), "[native func wait]", sciter.NewValue(true), sciter.NewValue())
}
func longOp(...) {
promise := args[0]
go waitHere(promise)
}
Turns out promise in go side is not a function. Error message is HV_INCOMPATIBLE_TYPE: ValueInvoke.
I think I'm very close to the solution.... What I do wrong here?
Well, it was tricky.
The problem was in a premature optimization in a way how go-sciter deals with scripting arguments. They are pointers (not values), that's why you have garbage in goroutine instead of promise (because longOp
goes out of scope and its arguments are freed by Sciter internally - it knows nothing that goroutine holds some pointer still).
Workaround (until I fix it) would be the following:
func longOp(...) {
promise := args[0] // `promise` here just a pointer
go waitHere(promise.Clone()) // make a real Value from it
}
Aha! The workaround works. I will use it now and looking forward to your fix. :)
apparently, there is no online equivalent of the sciter-sdk/doc/content/script/language/promise.htm
I've just found it: https://sciter.com/docs/content/sciter/promise.htm It is inside the DOM classes section unlike in offline docs where it is suited in Sciter Script's section.
I have the same problem. Could you show your full example codes? @AllenDang
My problem is here. #254
Thanks.
My code is below
It suppose to be a async call, but the main thread is blocked. Am I using await in the right way?