I want to run a long-running api call and subsequently, kill it using another api call. I have tried the following methods:
* def longQuery = async function() { karate.call('this:submit-long-running-sync-query.feature', {queryID: queryID})}
* karate.eval(longQuery())
This does not eval the async function and only returns when it timesout.
* def longQuery = function() { karate.call('this:submit-long-running-sync-query.feature', {queryID: queryID})}
* eval new java.lang.Thread(karate.toJava(longQuery)).start()
Caused by host exception: com.intuit.karate.KarateException: The value 'DynamicObject<JSFunction>#4bc59b27' cannot be passed from one context to another.
* def longQuery = function() { karate.call('this:submit-long-running-sync-query.feature', {queryID: queryIDtest})}
* eval new java.lang.Thread(longQuery).start()
Exception in thread "Thread-1" java.lang.IllegalStateException: Multi threaded access requested by thread Thread[Thread-1,5,main] but is not allowed for language(s) js
How do we execute an async feature test call on karate?
No, Karate's JS engine is a bit "different" and async is not supported.
For these advanced cases the recommendation is to write a bit of Java "glue" code (one-time only). Please refer to this as an example: https://twitter.com/getkarate/status/1417023536082812935
Related
I have the following code
async function func2() {
const promise = new Promise((res,rej) => {
const arr = new Array(10000000).fill('hehehehe');
const arr2 = JSON.stringify(arr);
const arr3 = new Array(10000000).fill('hehehehe');
return res('Completed Execution Of function #2');
})
return promise
}
async function func1() {
const promise = new Promise((res,rej) => {
const arr = [1,2,3];
const stringified = JSON.stringify(arr);
return res('Completed Execution of function #1');
})
return promise
}
func2().then(res => console.log(res))
func().then(res => console.log(res))
console.log('I am After Part')
The output of Above script is
As per my understanding, both function calls are passed to some services behind the scenes but func1 should get resolved first as there are no heavy calculations, but we see in output func2's response gets printed first and later func1's, What is the reason behind it??
Also, can we purposefully build this behavior in any other way??
There are a few background concepts that need to be covered to understand the behaviour you are seeing.
1. Tasks and the event loop:
https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide#tasks
Javascript has a task queue for managing callbacks and asynchronous behaviour.
Each task is run synchronously to completion before the next task is started (see next section).
JavaScript is single-threaded so only one task will run at a time.
(Note: for simplicity we're ignoring Workers; having a good understanding of tasks and how the JavaScript runtime works is necessary before looking at how Workers work within JavaScripts execution model)
The task queue is processed in order (i.e. the oldest task is processed next) and the task must finish before the next task will start.
Microtasks are special type of task that will run at the end of the current task before the next task runs (all current microtasks are completed before the next task will start).
Creating a promise (as shown in your example) queues a new microtask.
For simplicity I won't make any further distinction between tasks and microtasks and will refer to them both as tasks.
2. JavaScript's "run-to-completion" semantics:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#run-to-completion
https://www.pineboat.in/post/javascript-run-to-completion-event-loop-asynchronous-foundations/
https://exploringjs.com/es6/ch_async.html#_run-to-completion-semantics
Once a task has started, all of the JavaScript code within that task will run synchronously to completion before the next task or microtask is run.
The code can create new promises or add callbacks, but those callbacks will be invoked after the current task has completed.
3. Here is nodejs's documentation of the event loop.
It can give more insight into the details of how the event loop and tasks work.
https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#what-is-the-event-loop
4. MDN article introducing asynchronous JavaScript
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Introducing
With that background we can look at your question to explain what's happening.
both function calls are passed to some services behind the scenes
Both functions are queued as tasks to be executed later.
They are queued in the order that you create the promises:
func2().then(res => console.log(res))
func().then(res => console.log(res))
func2 is queued first and func is queued second.
but func1 should get resolved first as there are no heavy calculations
but we see in output func2's response gets printed first and later func1's, What is the reason behind it??
JavaScript doesn't have any concept of how "heavy" a function is.
All it knows is that func2 was queued first and func was queued second, so that is the order in which the tasks will run.
Once the func2 task is started it must finish before the next func task can be started.
That explains the output you are seeing.
The way to change the order of output would be to change how the tasks are queued and run.
A trivial answer is to change the order in which the tasks are queued:
func().then(res => console.log(res))
func2().then(res => console.log(res))
But that's not a very interesting answer.
Instead, lets use our understanding of tasks to change the result.
We observe that func2 does a lot of work that must be completed before the next task can start.
So, what if we break up that work into smaller tasks?
If you can do part of the work in one task, then do the rest of the work in another task, that gives func a chance to run in between.
Here is an example that splits up the work and uses setTimeout() to queue a new task that completes the work of func2.
async function func2() {
const promise = new Promise((res,rej) => {
const arr = new Array(10000000).fill('hehehehe');
const arr2 = JSON.stringify(arr);
// the callback passed to setTimeout will be queued
// as a new task and executed later.
setTimeout(() => {
const arr3 = new Array(10000000).fill('hehehehe');
return res('Completed Execution Of function #2');
}, 0);
})
return promise
}
You could make any sort of an async call to queue a new task (e.g. fetch/https request, reading/writing to the filesystem, or making a database call).
I want to use neon to perform an async task from nodejs to rust.
I want to call a function from nodejs with some data performAsyncTask(data, (err, result) => {}) and get back a result once rust has finished performing the task.
I looked at a basic async example using neon on their github: https://github.com/neon-bindings/examples/blob/main/async/native/src/lib.rs
Unfortunately, I can't seem to figure out how to access the data from the perform method
in the BackgroundTask.
If I get the argument passed in from nodejs this way
let arg0 = cx.argument::<JsValue>(0)?;, how can I access that within the perform method of the BackgroundTask?
I appreciate the help!
Thanks!
Since this is executing asynchronously, the result wont be available until after the perform_async_task() has returned. In javascript, you'd normally pass a callback to the function, which is then called when the result is available. Neon provides a specific shortcut to this via the .schedule() method.
fn schedule(self, callback: Handle<'_, JsFunction>)
The callback passed to .schedule() will be called after the task has completed. There is an example which shows this in: https://github.com/neon-bindings/examples/blob/e7b5e3c4ed35f6c5d84895c2f7e7b06389989b6f/fibonacci-async-task/native/src/lib.rs
The example shows both a synchronous and asynchronous implementation. The key parts of the async implementation are line 44, which gets the callback argument passed in from JS, and line 47 which passes the callback to the .schedule() function
43: let n = cx.argument::<JsNumber>(0)?.value() as usize;
44: let cb = cx.argument::<JsFunction>(1)?;
45:
46: let task = FibonacciTask { argument: n };
47: task.schedule(cb);
The rest should be handled by neon itself, based on the value returned from .complete() in your task implementation
I've written a simple service using redis to store data in memory or fetch from disc and then store in memory. I'm trying to now control for rare cases where fetching to redis is slow. I've seen one example (https://gist.github.com/stockholmux/3a4b2d1480f27df8be67#file-timelimitedredis-js) which appears to solve this problem but I've had trouble implementing.
The linked implementation is:
/**
* returns a function that acts like the Redis command indicated by cmd except that it will time out after a given number of milliseconds
*
* #param {string} cmd The redis commmand to execute ('get','hset','sort', etc.)
* #param {integer} timeLimit The number of milliseconds to wait until returning an error to the callback.
*
*/
function timeLimited(cmd, timeLimit) {
return function() {
var
argsAsArr = Array.prototype.slice.call(arguments),
cb = argsAsArr.pop(),
timeoutHandler;
timeoutHandler = setTimeout(function(){
cb(new Error('Redis timed out'));
cb = function() {};
}, timeLimit);
argsAsArr.push(function(err, values){
clearTimeout(timeoutHandler);
cb(err,values);
});
client[cmd].apply(client,argsAsArr);
};
}
however I don't understand how to implement this because client is never defined and the the redis key/value are never passed in. Could someone explain a little about how one could go about implementing this example? I've been searching for more information or a working example but not had any luck so far. Thank you.
This isn't very clearly written but when you call it with cmd (eg. SET, HSET, etc) and time limit it returns a function. You call this returned function with the values. I don't know where client comes from, I guess you need to have it in scope. This isn't very good code, I would suggest posting what you've written and asking how to achieve what you want with that.
I have a function which calls Concurrency::create_task to perform some work in the background. Inside that task, there is a need to call a connectAsync method on the StreamSocket class in order to connect a socket to a device. Once the device is connected, I need to grab some references to things inside the connected socket (like input and output streams).
Since it is an asynchronous method and will return an IAsyncAction, I need to create another task on the connectAsync function that I can wait on. This works without waiting, but complications arise when I try to wait() on this inner task in order to error check.
Concurrency::create_task( Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService::FromIdAsync( device_->Id ) )
.then( [ this ]( Windows::Devices::Bluetooth::Rfcomm::RfcommDeviceService ^device_service_ )
{
_device_service = device_service_;
_stream_socket = ref new Windows::Networking::Sockets::StreamSocket();
// Connect the socket
auto inner_task = Concurrency::create_task( _stream_socket->ConnectAsync(
_device_service->ConnectionHostName,
_device_service->ConnectionServiceName,
Windows::Networking::Sockets::SocketProtectionLevel::BluetoothEncryptionAllowNullAuthentication ) )
.then( [ this ]()
{
//grab references to streams, other things.
} ).wait(); //throws exception here, but task executes
Basically, I have figured out that the same thread (presumably the UI) that creates the initial task to connect, also executes that task AND the inner task. Whenever I attempt to call .wait() on the inner task from the outer one, I immediately get an exception. However, the inner task will then finish and connect successfully to the device.
Why are my async chains executing on the UI thread? How can i properly wait on these tasks?
In general you should avoid .wait() and just continue the asynchronous chain. If you need to block for some reason, the only fool-proof mechanism would be to explicitly run your code from a background thread (eg, the WinRT thread pool).
You could try using the .then() overload that takes a task_options and pass concurrency::task_options(concurrency::task_continuation_context::use_arbitrary()), but that doesn't guarantee the continuation will run on another thread; it just says that it's OK if it does so -- see documentation here.
You could set an event and have the main thread wait for it. I have done this with some IO async operations. Here is a basic example of using the thread pool, using an event to wait on the work:
TEST_METHOD(ThreadpoolEventTestCppCx)
{
Microsoft::WRL::Wrappers::Event m_logFileCreatedEvent;
m_logFileCreatedEvent.Attach(CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS));
long x = 10000000;
auto workItem = ref new WorkItemHandler(
[&m_logFileCreatedEvent, &x](Windows::Foundation::IAsyncAction^ workItem)
{
while (x--);
SetEvent(m_logFileCreatedEvent.Get());
});
auto asyncAction = ThreadPool::RunAsync(workItem);
WaitForSingleObjectEx(m_logFileCreatedEvent.Get(), INFINITE, FALSE);
long i = x;
}
Here is a similar example except it includes a bit of Windows Runtime async IO:
TEST_METHOD(AsyncOnThreadPoolUsingEvent)
{
std::shared_ptr<Concurrency::event> _completed = std::make_shared<Concurrency::event>();
int i;
auto workItem = ref new WorkItemHandler(
[_completed, &i](Windows::Foundation::IAsyncAction^ workItem)
{
Windows::Storage::StorageFolder^ _picturesLibrary = Windows::Storage::KnownFolders::PicturesLibrary;
Concurrency::task<Windows::Storage::StorageFile^> _getFileObjectTask(_picturesLibrary->GetFileAsync(L"art.bmp"));
auto _task2 = _getFileObjectTask.then([_completed, &i](Windows::Storage::StorageFile^ file)
{
i = 90210;
_completed->set();
});
});
auto asyncAction = ThreadPool::RunAsync(workItem);
_completed->wait();
int j = i;
}
I tried using an event to wait on Windows Runtime Async work, but it blocked. That's why I had to use the threadpool.
I am new to multithreading in Android and I have a doubt. I have a AsyncTask instance which I call as BackGroundTask and I start this as:
BackGroundTask bgTask = new BackGroundTask();
bgTask.execute();
However I would like to wait until this call is finished its execution, before proceeding to the other statements of code without blocking UI thread and allowing user to navigate through application.
Please help me so that I can achieve this.
put your code inside onPostExecute method of AsyncTask, which you
wants to execute after work done By worker thread.
Try using bgTask.execute().get() this will wait for the background task to finish before moving to the next instruction in the called thread. (Please note that this will block the called thread until background task finishes)
I have found the answer at
How do I retrieve the data from AsyncTasks doInBackground()?
And the answer is to use callback as shown below which is copied from above shared link:
The only way to do this is using a CallBack. You can do something like this:
new CallServiceTask(this).execute(request, url);
Then in your CallServiceTask add a local class variable and class a method from that class in your onPostExecute:
private class CallServiceTask extends AsyncTask<Object, Void, Object[]>
{
RestClient caller;
CallServiceTask(RestClient caller) {
this.caller = caller;
}
protected Object[] doInBackground(Object... params)
{
HttpUriRequest req = (HttpUriRequest) params[0];
String url = (String) params[1];
return executeRequest(req, url);
}
protected onPostExecute(Object result) {
caller.onBackgroundTaskCompleted(result);
}
}
Then simply use the Object as you like in the onBackgroundTaskCompleted() method in your RestClient class.
A more elegant and extendible solution would be to use interfaces. For an example implementation see this library. I've just started it but it has an example of what you want.