I'm writing unit tests for a method that runs a primary function and then logs details about the request asynchronously.
def someMethod(data: Object): SomeType =
for {
result <- someOtherMethod(data).withLogging(logMethod)
}
The method logMethod is an async task. In my tests, I want to ensure that the logger is receiving a message, however, the thread completes too soon at times making the test flaky and causing an Unsatisfied result sometimes.
Example test case:
it("logs an error if an upload was attempted with some failure case") {
val uploadData = someData
mockSomeCall()
mockAnotherCall()
testController.methodWeAreTesting(uploadData).shouldBeRight()
Thread.sleep(75)
(stubLogger
.warn(_: RichMsg, _: Throwable, _: AnyId)(_: () => SourceLocation))
.verify(where { (msg: RichMsg, _, _, _) =>
msg.toString.equals(s"Some specific message")
})
}
I'm not enjoying adding a Thread.sleep every time I need to ensure that the logger is receiving a specific message. I'd like to be able to possibly wrap the stubLogger expectation.
Let me know if more information is needed.
I think promise is what you need to add in logMethod.
As per the documentation:
While futures are defined as a type of read-only placeholder object
created for a result which doesn’t yet exist, a promise can be thought
of as a writable, single-assignment container, which completes a
future. That is, a promise can be used to successfully complete a
future with a value (by “completing” the promise) using the success
method. Conversely, a promise can also be used to complete a future
with an exception, by failing the promise, using the failure method.
A promise p completes the future returned by p.future. This future is
specific to the promise p. Depending on the implementation, it may be
the case that p.future eq p.
In the tests, once you get back the result, you can compare the result with the message that you are trying to compare.
A sample code is shown below:
object Test1 extends App {
import scala.concurrent.{Future, Promise}
import scala.concurrent.ExecutionContext.Implicits.global
import scala.util.{Success, Failure}
var promiseMessage: String = _
val promise = Promise[String] //The promise will hold a string
//A future tells the System to spawn a new thread and run the code block inside it
val logMethod = (elem: String) => Future{
promise.success(elem)
elem
}
def method(data: String): Future[String] = {
for {
result <- logMethod(data)
} yield result
}
val f1 = method("Hi!! I love scala async programming")
promise completeWith f1
val promiseFuture = promise.future
promiseFuture onComplete {
case Success(value) =>
promiseMessage = value
println(promiseMessage)
case Failure(ex) => println(ex)
}
Await.result(promiseFuture, 100 seconds)
if (promiseMessage == "Hi!! I love scala async programming") println("correct")
}
In the code, promise is a Promise object which promises a string when the future gets complete. All you need to do is complete the promise with future as shown in:
promise completeWith f1 and then, add a handler as to what to do when it is successful or failure using promiseFuture onComplete.
If you want to check if logging happened you can await on the promiseFuture or else continue with the further process and when the logging is done, the promise will print that is successful as shown in the code.
Let me know it helps!!
Related
I have a method that I want to finish before any code after it can be ran but am lost in understand external links when is comes to this.
In one method I have the following code
var x = someMethod("1","2","3"); // Finish before anything below can be ran
The method itself is simple
function someMethod(x,y,z){
if(1){
return "sdfh"
} else if(2){
return "asdf"
} else {
return "ljkk"
}
}
How can I retrieve x before continue the code below it. Ive seen examples of nested functions, await, async but am lost
Try:
const someMethod = (x, y, z) => {
...
};
const otherMethod = async () => {
let x = 'before value';
console.log(`before someMethod x: ${x}`);
// Finish before anything below can be ran
x = await someMethod("1", "2", "3");
console.log(`after someMethod x: ${x}`);
};
Basically you are defining the function which has the await call as an asynchronous function using the async keyword in the function declaration - and can signify the portion of the code which you would like to wait by prepending with await. There are nuances to this - but hopefully this helps.
Java script is single thread and synchronous. I recommend checking out JavaScript promises. However I would assume your code executes synchronously until it hits something like a AJAX that is asynchronous.
check this answer out:
When is JavaScript synchronous?.
I have made a few questions about this already, but maybe this question would result in better answers(i'm bad at questions)
I have one class, called FOO, where I call an async Start function, that starts the process that the class FOO was made to do. This FOO class does a lot of different calculations, as well as posting/getting the calculations using the node.js "requets" module.
-I'm using electron UI's (by pressing buttons, that executes a function etc..) to create and Start the FOO class-
class FOO {
async Start(){
console.log("Start")
await this.GetCalculations();
await this.PostResults()
}
async PostResults(){
//REQUESTS STUFF
const response = {statusCode: 200} //Request including this.Cal
console.log(response)
//Send with IPC
//ipc.send("status", response.statusCode)
}
async GetCalculations(){
for(var i = 0; i < 10; i++){
await this.GetCalculation()
}
console.log(this.Cal)
}
async GetCalculation(){
//REQUEST STUFF
const response = {body: "This is a calculation"} //Since request module cant be used in here.
if(!this.Cal) this.Cal = [];
this.Cal.push(response)
}
}
var F1 = new FOO();
F1.Start();
Now imagine this code but with A LOT more steps and more requests ect. where it might take seconds/minutes to finish all tasks in the class FOO.
-Electron got a stop button that the user can hit when he wants the calculations to stop-
How would I go about stopping the entire class from continuing?
In some cases, the user might stop and start right after, so I have been trying to figure out a way to STOP the code from running entirely, but where the user would still be able to create a new class and start that, without the other class running in the background.
I have been thinking about "tiny-worker" module, but on the creation of the worker, it takes 1-2 seconds, and this decreases the purpose of a fast calculation program.
Hopefully, this question is better than the other ones.
Update:
Applying the logic behind the different answers I came up with this:
await Promise.race([this.cancelDeferred, new Promise( async (res, req) => {
var options ={
uri: "http://httpstat.us/200?sleep=5000"
}
const response = await request(options);
console.log(response.statusCode)
})])
But even when the
this.cancelDeferred.reject(new Error("User Stop"));
Is called, the response from the request "statuscode" still gets printed out when the request is finished.
The answares I got, shows some good logic, that I didn't know about, but the problem is that they all only stop the request, the code hanlding the request response will still execute, and in some cases trigger a new request. This means that I have to spam the Stop function until it fully stops it.
Framing the problem as a whole bunch of function calls that make serialized asynchronous operations and you want the user to be able to hit a Cancel/Stop button and cause the chain of asynchronous operations to abort (e.g. stop doing any more and bail on getting whatever eventual result it was trying to get).
There are several schemes I can think of.
1. Each operation checks some state property. You make these operations all part of some object that has a aborted state property. The code for every single asynchronous operation must check that state property after it completes. The Cancel/Stop button can be hooked up to set this state variable. When the current asynchronous operation finishes, it will abort the rest of the operation. If you are using promises for sequencing your operations (which it appears you are), then you can reject the current promise causing the whole chain to abort.
2. Create some async wrapper function that incorporates the cancel state for you automatically. If all your actual asynchronous operations are of some small group of operations (such as all using the request module), then you can create a wrapper function around whichever request operations you use that when any operation completes, it checks the state variable for you or merges it into the returned promise and if it has been stopped, it rejects the returned promise which causes the whole promise chain to abort. This has the advantage that you only have to do the if checks in one place and the rest of your code just switches to using your wrapped version of the request function instead of the regular one.
3. Put all the async steps/logic into another process that you can kill. This seems (to me) like using a sledge hammer for a small problem, but you could launch a child_process (which can also be a node.js program) to do your multi-step async operations and when the user presses stop/cancel, then you just kill the child process. Your code that is monitoring the child_process and waiting for a result will either get a final result or an indication that it was stopped. You probably want to use an actual process here rather than worker threads so you get a full and complete abort and so all memory and other resources used by that process gets properly reclaimed.
Please note that none of these solutions use any sort of infinite loop or polling loop.
For example, suppose your actual asynchronous operation was using the request() module.
You could define a high scoped promise that gets rejected if the user clicks the cancel/stop button:
function Deferred() {
let p = this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
this.then = this.promise.then.bind(p);
this.catch = this.promise.catch.bind(p);
this.finally = this.promise.finally.bind(p);
}
// higher scoped variable that persists
let cancelDeferred = new Deferred();
// function that gets called when stop button is hit
function stop() {
// reject the current deferred which will cause
// existing operations to cancel
cancelDeferred.reject(new Error("User Stop"));
// put a new deferred in place for future operations
cancelDeferred = new Deferred();
}
const rp = require('request-promise');
// wrapper around request-promise
function rpWrap(options) {
return Promise.race([cancelDeferred, rp(options)]);
}
Then, you just call rpWrap() everywhere instead of calling rp() and it will automatically reject if the stop button is hit. You need to then code your asynchronous logic so that if any reject, it will abort (which is generally the default and automatic behavior for promises anywa).
Asynchronous functions do not run code in a separate thread, they just encapsulate an asynchronous control flow in syntactic sugar and return an object that represents its completion state (i.e. pending / resolved / rejected).
The reason for making this distinction is that once you start the control flow by calling the async function, it must continue until completion, or until the first uncaught error.
If you want to be able to cancel it, you must declare a status flag and check it at all or some sequence points, i.e. before an await expression, and return early (or throw) if the flag is set. There are three ways to do this.
You can provide a cancel() function to the caller which will be able set the status.
You can accept an isCancelled() function from the caller which will return the status, or conditionally throw based on the status.
You can accept a function that returns a Promise which will throw when cancellation is requested, then at each of your sequence points, change await yourAsyncFunction(); to await Promise.race([cancellationPromise, yourAsyncFunction()]);
Below is an example of the last approach.
async function delay (ms, cancellationPromise) {
return Promise.race([
cancellationPromise,
new Promise(resolve => {
setTimeout(resolve, ms);
})
]);
}
function cancellation () {
const token = {};
token.promise = new Promise((_, reject) => {
token.cancel = () => reject(new Error('cancelled'));
});
return token;
}
const myCancellation = cancellation();
delay(500, myCancellation.promise).then(() => {
console.log('finished');
}).catch(error => {
console.log(error.message);
});
setTimeout(myCancellation.cancel, Math.random() * 1000);
I don't like anything I've seen so far...
Module
import lineReader from 'line-reader'
let bigFile = './huge-file.csv'
export default class DooDad {
constructor() {
this.dictionary = new Map()
// Something like this seems like it'd be nice...
// await this.load()
}
load() {
return new Promise((resolve, reject) => {
lineReader.eachLine(bigFile, (line, last) => {
// this.dictionary = The contents of huge-file.csv
})
})
}
doStuff(foo) {
// Uses this.dictionary to do something interesting
// Problem: Unusable without first calling and waiting for this.load()
}
}
Usage
import DooDad from '../doodad'
let doodad = new DooDad()
// We have to first call and wait for load() before doodad is useable
doodad.load().then(x => {
doodad.doStuff()
})
Seems like you'd either want to...
1) Make the loading synchronous
2) Make a static create function on DooDad that returns a promise that resolves to a new instance of a DooDad
3) Make the constructor return a Promise (seems weird) Asynchronous constructor
4) Emit an event when its done loading
5) Leave it how it is
6) ????
doodad.load().then() makes perfect sense to me. You don't want constructors to be async so it makes sense to have .load() be where the async stuff is.
The other pattern I've seen is you export a factory-type function that returns a promise and when that promise is resolved, the resolved value is your fully formed object. This has the advantage of there is no access to the object until the async stuff is done and there is no temptation by calling code to try to use it before it is ready.
import makeDooDad from '../doodad'
makeDooDad().then(doodad => {
// you only get access to the object here after it's been fully
// initialized
doodad.doStuff();
});
And, the makeDooDad() factory function does something like this inside of your module:
function makeDooDad() {
let d = new DooDad();
// fully initialize the doodad object before resolving the promise
// and before returning the object
return d.load().then(() => {
// let the object itself by the resolved value
return d;
});
}
As for your other options:
Make the loading synchronous
This could be OK only if it is only done at server startup time. There is generally no real cost to doing some synchronous I/O at server startup time and often it makes things a lot simpler. For example, require() itself does synchronous I/O.
Make a static create function on DooDad that returns a promise that resolves to a new instance of a DooDad
That is essentially what I recommended above with the factory function. This is often times a good option.
Make the constructor return a Promise (seems weird) Asynchronous constructor
No. Don't really want to do that. Constructors should return objects, not promises. Use a factory function to return a promise.
Emit an event when its done loading
There are other pieces of code that do this such as creating a writeStream, emits an open event on the stream when the stream is actually open. But, in the days of promises, this isn't my favorite way of doing things for other types of objects that aren't already using lots of events.
Leave it how it is
It's OK as is, but I prefer the factory function that returns a promise.
var assert = require('assert');
var parseJSON = require('json-parse-async');
var contact = new Object();
contact.firstname = "Jesper";
contact.surname = "Aaberg";
contact.phone = ["555-0100", "555-0120"];
var contact2 = new Object();
contact2.firstname = "JESPER";
contact2.surname = "AABERG";
contact2.phone = ["555-0100", "555-0120"];
contact.toJSON = function(key) {
var replacement = new Object();
for (var val in this) {
if (typeof(this[val]) === 'string')
replacement[val] = this[val].toUpperCase();
else
replacement[val] = this[val]
}
return replacement;
};
var jsonText = JSON.stringify(contact);
contact = JSON.parse(jsonText);
console.log(contact);
console.log(contact2);
assert.deepEqual(contact, contact2, 'these two objects are the same');
What are the asynchronous equivalent functions of JSON.parse, JSON.stringify and assert.deepEqual? I am trying to create a race condition and non-deterministic behavior within the following code but I have not been able lto find non-blocking, asynchronous equivalents of the functions mentioned above.
node.js does not have an actual asynchronous JSON parser built-in. If you want something that will actually do the parsing outside the main node.js Javascript thread, then you would have to find a third party module that parses the JSON outside of the Javascript thread (e.g. in a native code thread or in some other process). There are some modules in NPM that advertise themselves as asynchronous such as async-json-parser or async-json-parse or json-parse-async. You would have to verify that whichever implementation you were interested in was truly an asynchronous implementation (your Javascript continues to run while the parsing happens in the background).
But, reading the detail in your question about the problem you're trying to solve, it doesn't sound like you actually need a parser that truly happens in the background. To give you your ability to test what you're trying to test, it seems to me like you just need an indeterminate finish that allows other code to run before the parsing finishes. That can be done by wrapping the synchronous JSON.parse() in a setTimeout() with a promise that has a random delay. That will give some random amount of time for other code to run (to try to test for your race conditions). That could be done like this:
JSON.parseAsyncRandom = function(str) {
return new Promise(function(resolve, reject) {
// use a random 0-10 second delay
setTimeout(function() {
try {
resolve(JSON.parse(str));
} catch(e) {
reject(e);
}
}, Math.floor(Math.random() * 10000));
});
}
JSON.parseAsyncRandom(str).then(function(obj) {
// process obj here
}, function(err) {
// handle err here
});
Note: This is not true asynchronous execution. It's an asynchronous result (in that it arrives some random time later and other code will run before the result arrives), but true asynchronous execution happens in the background in parallel with other JS running and this isn't quite that. But, given your comment that you just want variable and asynchronous results for testing purposes, this should do that.
I've recently faced this problem myself, so I decided to create a library to handle JSON parsing in a really asynchronous way.
The idea behind it is to divide the parsing process into chunks, and then run each separately in the event loop so that other events (user interactions, etc) can still be evaluated within a few milliseconds, keeping the UI interactive.
If you are interested, the library it's called RAJI and you can find it here: https://github.com/federico-terzi/raji
After installing RAJI, you can then convert your synchronous JSON.parse calls into async raji.parse calls, such as:
const object = await parse(payload);
These calls won't block the UI
You can use 'bluebird', like this example to convert calling function to promise.
I write code below using javascript es6.
const Promise = require('bluebird')
function stringifyPromise(jsonText) {
return Promise.try(() => JSON.stringify(jsonText))
}
function parsePromise(str) {
return Promise.try(() => JSON.parse(str))
}
stringifyPromise(contact)
.then(jsonText => parsePromise(jsonText))
.then(contact => {
assert.deepEqual(contact, contact2, 'these two objects are the same')
})
})
I'm writing a Windows 8 app in HTML / JS and have a button on a form with a click event handler. When clicked the first thing the button does is this:
WinJS.Promise.then(openDB()).done(console.log("PROMISE DONE"));
The openDB function looks like this:
function openDB() {
console.log("openDb...");
var req = indexedDB.open("MyDB", 1);
req.onsuccess = function(evt) {
var data = evt.target.result;
console.log("openDb DONE");
}
}
(I also have onerror and onupgradeneeded callbacks on the req object but have left these out for brevity).
I'm clearly misunderstanding how promises are supposed to work but I thought that I could chain multiple THEN calls on a promise, and the final call DONE would only fire when all the THEN calls have executed. Problem is that the console shows 'openDb ...', followed by 'PROMISE DONE', followed by 'OpenDb done'. So the DONE call is being executed before the THEN call. Can anyone explain why this is happening?
Your fundamental issue here is that the "then" method returns a new promise. If the function you called returns a promise, that's the promise that's returned (and thus chained off). If your function does not return a promise, a new (already completed) promise is returned that give you the value that's returned.
Looking at your openDB function, what does it return? Actually, it returns undefined. And more importantly, it kicks off async work and then returns immediately; the async operation doesn't complete until later. Thus, you get the behavior you're seeing.
So what you need to do is get openDB to return a promise that doesn't complete until the database open operation completes. WinJS promises are really bad at this, so the API is ugly. Hopefully they'll fill in the missing piece in Win8.1.
So, you need to create a new promise, and complete it when the async work's done. That looks something like this:
function openDB() {
var complete;
var = new Promise(function (c, e, p) {
complete = c;
});
console.log("openDb...");
var req = indexedDB.open("MyDB", 1);
req.onsuccess = function(evt) {
var data = evt.target.result;
console.log("openDb DONE");
complete(data);
}
return p;
}
The new Promise(function (c, e, p) { ... }) call creates a new promise object. The function you pass is itself passed three functions - one to call on successful completion of the object (c for complete), one to call if the promise unsuccessfully completes (e for error), and one to call to report progress (p for progress). We sock away the completion callback into a variable here for use later.
Now, in the success callback from indexedDB, note that we invoke the complete callback, passing the data we got. This will set the promise to completed state.
Finally, we return the created promise. Note that this return happens synchronously; the function returns before the onsuccess handler gets called.
This should get you what you want - it'll hold off the promise chain until the database open completes. You should probably hook up the error handler to something as well.
Now, having done this, the call to WinJS.Promise.then() is also incorrect, or at least unnecessary. You should instead just do:
openDB().done(function () { console.log('Promise Done'); });
Since openDB itself returns a promise, you don't need the extra wrapping in another promise you're doing.