How to invoke viewcomponent syncrounous - razor-pages

I see examples of invoking a viewcomponent like this within a razorpage
#await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
The docs also mention there is an synchronous method Invoke, but I cant find an example of using it. When I try to use Component.Invoke, I get this
'IViewComponentHelper' does not contain a definition for 'Invoke' and
no accessible extension method 'Invoke' accepting a first argument of
type 'IViewComponentHelper' could be found

The docs also discuss how to perform synchronous work in a ViewComponent. Your component class will include a synchronous Invoke method, but you still call it using await:
#await Component.InvokeAsync("PriorityList", new { maxPriority = 4, isDone = true })
The method signature of PriorityList.Invoke is synchronous, but Razor
finds and calls the method with Component.InvokeAsync in the markup
file.
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-3.0#perform-synchronous-work

Related

setTimeout & "this" keyword in nodejs

const person = {
talk() {
setTimeout(function () {
console.log(this);
}, 1000);
},
};
person.talk();
I know when you call a stand-alone function in javascript, "this" will refer to the global object (i.e., the window object in browser, or the global object in nodejs).
Since a callback function is a stand-alone function, I expect it will print window/global in the above example.
However, when I test it in browser, it did return the window object.
But when I run it in node, it returns a Timeout object rather than the global object. What is the reason behind it?
setTimeout() is not actually part of the Javascript standard - it is supplied by the host environment.
In the nodejs implementation, a timer is an actual object and nodejs calls the timer callback by calling a method on that object like this:
timer._onTimeout();
where this is set in the contructor of the object like this:
this._onTimeout = callback;
to the timer callback. Thus, this will be the timer object (due to the method call). You can examine the nodejs timer object source yourself here.
One of the reasons for nodejs to turn a timer ID into an object is that it also has other methods such as .ref() and .unref() which are cleaner to implement and expose to the programmer if the timer handle is an actual object rather than adding more functions to the global namespace.
The browser has a different implementation that calls the callback as a normal function. And, in Javascript (when not in strict mode) calling a normal function sets this to the global object in the function.
As I said in the comments, you should NOT rely on any value of this that is not explicitly documented to be what you want or controlled by the way you have called things. To do so is just playing roulette.
If you want to explicitly reference the global object, then I'd suggest you just specifically refer to the global object as window.x or global.x depending upon your environment.
The answer to your question can be found here:
Different behaviour of setTimeout in nodejs and Chrome.
In short, Node's setTimeout is a different function than a browser's setTimeout, despite having similar functionality and identical name. I do not know the underlying reason they were created to have different this references, but they do.
The reason behind this is that this binding is determined based on where it was called not where it is declared.
There are four rules according to You don't Know JS books
Default Binding
example
let world = "hello world"
function hello() {
console.log(this.world)
console.log(this)
}
hello() // prints hello world and global object
//the call site is on the global environment
Implicit Binding
example
let object1 = {
world: "I am being called from object1 site ",
hello: hello
}
let object2 = {
world: "I am in 2",
object1: object1
}
object2.object1.hello() //will print " I am being called from object1 site because of the taking the object that is closest level to the function and that is objec1"
obj.hello() // print "I am being called from object1 site and object1 properties
Explicit Binding
This occurs when you are 'explicit' about the object you want this to refer to and in this case you use call, apply and bind (which is more stronger in binding this to expected object)
Example
hello.call(object1) in this case this will refer to object1. In an event where call or apply does not work you can use bind to make a hard bind .That is why you would see this pattern a lot
Let say you want to refer to the person object
const person = {
talk() {
setTimeout(
function () {
console.log(this);
}.bind(this),
1000
);
},
};
person.talk(); // `this` will refer to the person object
Let say you want to refer to global object in Node
let globalObject = globalThis;
const person = {
talk() {
setTimeout(
function () {
console.log(this);
}.bind(globalObject),
1000
);
},
};
person.talk(); // this will refer to global object
New Binding: this is using keyword new to create an object
Example let b = new life()
To determine this in code you have to know how it was used in the call site and they take precedence over in this order: new binding > explicit binding > implicit binding > default binding

jest assert a function have been called twice and both times with particular argument

I am testing a Vue component that dispatches an action(functionx) on mount. The same action(functionx) is dispatched when a particular refresh button is clicked. I am testing the behavior of that refresh button - that is the vuex dispatch action is called with argument 'functionx'. Here is my test:
it('makes an api call to server when refresh button is clicked', () => {
store.dispatch = jest.fn();
const wrapper = mount(Categories, {
sync: false,
store,
localVue
});
const refreshButton = wrapper.find('span.fa-sync');
refreshButton.trigger('click');
expect(store.dispatch).toHaveBeenCalledWith('categoryStore/fetchCategories');
})
});
which passes. Now since the same action is dispatched initially when the component is mounted. So in total dispatch is called twice. I know I can use .toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....) to check that dispatch was called both times with same argument, but for that I will have to write two expect statements, like below:
expect(store.dispatch).toHaveBeenNthCalledWith(1, 'categoryStore/fetchCategories');
expect(store.dispatch).toHaveBeenNthCalledWith(2, 'categoryStore/fetchCategories');
Is there any way I can achieve the above thing in one statement? Any matcher function or any property on the expect object that can be used?
Sadly there's currently no easy matcher for this situation (list of matchers).
You could do it "manually" using the .mock parameter, something like this:
function assertFunctionWasCalledTimesWith(jestFunction, times, argument) {
expect(jestFunction.mock.calls.filter((call) => call[0] === argument).length)
.toBe(times)
}
(Using the filter method makes the times assertion only take into account the calls that have given argument)
Using the above function you could assert your code like this:
assertFunctionWasCalledTimesWith(store.dispatch, 2, 'categoryStore/fetchCategories')
Of course, the message when the test fails won't be very descriptive, but it works, anyway.

How to test the content of callback of method

I might not be getting something but I am trying to test the callback content of a method but without calling the method.
The function I am trying to test
functionToSkip(param1, param2, function(arg1, arg2){
if(arg1){
// Do some things here
} else {
// Do other things here
}
}
What I am trying to do is to test the content of the callback function with differents args values that I can change in the tests and the parameter of the functionToSkip can be anything.
All I successfully did is to skip the call of the function but I cannot call the callback method.
I did stub the function to skip and even trying to give values to the callback method but there is not any logs showing.
var spy = sinon.stub(Class, "functionToSkip").calledWith(param1, param2, ("arg1","arg2"))
The main method that is calling the stubbed function works since I can see the logs prior of the function when I call it in the tests.
First of all, if functionToSkip is an instance method on Class, it will be a property on Class.prototype, not Class itself. In order to stub, you can do one of two things:
Create an instance, and create the stub:
instance = new Class(/*costructor arguments*/)
var stub = sinon.stub(instance, 'functionToSkip')
Or, stub on the prototype:
var stub = sinon.stub(Class.prototype, 'functionToSkip');
In the second case, since class prototypes are global state, I'd recommend restoring it-- preferably in something like mocha afterEach to ensure it gets cleaned up whether your test is successful or not. This way it doesn't screw with other tests in your run:
stub.restore()
Between the two, though, I recommend the first approach.
Next up... If you want to make assertions on the content of calls, the firs thing you'll probably want to do is assert that it was in fact called with the signature you're looking for:
sinon.assert.calledWith(stub, sinon.match.any, sinon.match.any, sinon.match.func)
The any matcher allows any value, and the func matcher requires a func. After that, you can obtain the callback function like so:
var cb = stub.firstCall.args[2]
And invoke it like so:
cb('arg1', 'arg2');
As to what assertions you'd do after invoking the callback function-- I'd have to know more about what you're trying to test about it to make recommendations.

Node.js Async Waterfall Hangs

I am currently implementing an API built using Express.js, following the MVCS pattern for my design. After reading about the Async module, I came to the conclusion that it would be a good idea for me to take advantage of its powerful methods. Unfortunately, I am running into a problem I can't seem to fix, and was wondering if someone could give me some advice. Let's take look at the code:
'use strict'
_ = require 'lodash'
async = require 'async'
validator = require 'express-validator'
class BaseService
constructor: (#model, #relationships, #fields) ->
list: (req, callback) ->
async.waterfall [
validate(req).bind(this),
query.bind(this)
], callback
validate = (request) ->
valid = request
(next) ->
next null, valid
return
query = (valid) ->
query = #model.find({})
if valid.query.q
query = query.where(valid.query.q)
if valid.query.sort
query = query.sort(valid.query.sort)
if valid.query.select
query = query.select(valid.query.select)
# Requests hangs at this point. Any ideas why?
(next) ->
query.exec next
return
module.exports = BaseService
Basically, I would like to first validate the query string that was passed with the request. Then, a Mongoose query is built depending on whether certain fields are present or not in the validated object. Lastly, it should execute the query and pass the results to the callback function. Here my implementation fails as it hangs, and the callback is never executed. I commented the line in the code snippet, to give you all a better idea of what is going on.
Can someone please point me in the right direction?
Your main problem is your query method signature needs to accept a callback as the last argument.
query = (valid, callback) ->
For waterfall, the first worker function takes (callback), but the rest of them take (previousResult, callback).
Also, given how you are using your query method, it does not need to return a function as you have it doing. Just accept the callback as an argument and invoke it when ready to move on to complete the waterfall.
Aside: using "query" for both a method and a local variable in a coffeescript class is error prone and confusing. Use a different name for the local variable such as "modelQuery".

Given the package, class, function(s), and parameters in Strings, how can I dynamically invoke a function in AS3?

I need to send requests between two separate .swfs, A and B. I have an interface, IRequest with the following methods:
public interface IRequest {
function get packagePath():String;
function get className():String;
function get functions():Vector.<String>;
function get parameters():Array;
function execute():void;
}
I implement it in a class, Request. One can create a new request as follows:
RequestManager.addToQueue(new Request("com.myPackage", "MyClass", "instance.method1.method2", "parameter"));
This creates a new Request with a supplied package, class-name, list of functions and parameters.
Things become complicated with a chain of function-calls and deciding if a function is actually a function or property (public function getMyThing():Object vs public function get myThing():Object).
For example, things are simple enough if the desired Request is new Request("com.myPackage", "MyClass", "getInstance", "");
Invoking that method is as simple as:
var theClass:Class = getDefinitionByName(packagePath + "." + className) as Class;
var theInstance:Object = theClass[functions[0]](); // Invokes com.myPackage.MyClass.getInstance()
However, this won't work if getInstance is a property/getter. Also, if there are numerous method calls, I'm not sure how to invoke the chain in one call. For example:
var theClass:Class = getDefinitionByName(packagePath + "." + className) as Class;
var object = theClass[functions[0]]()[functions[1]()[functions[2](); // Invokes com.myPackage.MyClass.firstMethod.secondMethod.thirdMethod()
However, I need to do this dynamically, and I don't see an easy way of dynamically chaining those [, ].
If anyone knows a nice way for me to be able to invoke methods from a String, that's essentially what I want to do.
"com.myPackage.MyClass.firstMethod.secondMethod.thirdMethod()", parameters
Thanks for the help,
I think doing a check whether that argument actually holds a function before invoking it would help.
var theClass:Class = getDefinitionByName(packagePath + "." + className) as Class;
if(theClass[functions[0]] is Function){
var theInstance:Object = theClass[functions[0]](); // Invokes com.myPackage.MyClass.getInstance()
}

Resources