I am getting this error and I am not sure why. In my dialog class I have the Promse and the fail logic. I am getting this build error any help would be great.
Severity Code Description File Project Line Suppression State
Error TS2740 (TS) Type 'Promise' is missing the following properties from type 'JQueryPromise': state, always, done, fail, and 2 more.
var responsePromse = this.agentManager.getStyleGuideByAgentId(this.model.Id);
responsePromse.then((response) => {
this.styleguideNote.AgentType = response.responseObject.Name;
}).fail(() => {
this.relatedTemplates.loadingState = 0;
});
AgentManager
getStyleGuideByAgentId(Id: number): JQueryPromise<any> {
var request = this.agentsService.getStyleGuideByAgentId(Id);
console.log(request);
return request;
}
AgentService
getStyleGuideByAgentId(Id: number) {
var x = this.http.post(this.apiUrls.GetStyleGuideNotes, JSON.stringify(Id), { headers: ServiceBase.headers }).toPromise();
return x;
}
Conroller
[HttpPost]
public IHttpActionResult GetStyleGuideNoteById(long agentId)
{
var dbResult = StyleGuideNotesDataService.GetStyleGuideNoteById(agentId);
var styleguideNote = dbResult
.Select(x=> new
{
Section =x.Section,
AgentType = x.AgentType,
Status = x.Status.Name
})
.Distinct()
.ToList();
return Ok(styleguideNote);
}
TS Error message like this format Type 'A' is missing following properties from type 'B' means that, you typed 'B' explicitly to a value, but type of the value is actually 'A'.
so, You typed something explicitly as JQueryPromise, but that thing was actually Promise.
I think this code makes error.
getStyleGuideByAgentId(Id: number): JQueryPromise<any> {
var request = this.agentsService.getStyleGuideByAgentId(Id);
console.log(request);
return request;
}
I'm not sure but getStyleGuideByAgentId actually returns standard Promise, not JqueryPromise due to toPromise()
so, changing code like this might be solve your problem.
async getStyleGuideByAgentId(Id: number): Promise<any> {
var request = await this.agentsService.getStyleGuideByAgentId(Id);
console.log(request);
return request;
}
Related
I use the following code to show tree items,
https://github.com/microsoft/vscode-extension-samples/tree/master/tree-view-sample
The items which is shown in the tree is related to a file, if the file changed the number of the tree items should be changed accordingly(using createFileSystemWatcher which works ok), currently I’ve add the code of the file watcher and when debug it stops there (on the getChildren function when I'm changing the file) and I see that I’ve provided the new updated entries (in the code),however the tree doesn’t refreshed with the new data, any idea what am I missing here ? somehow the new updated data is not reflected in the tree. as I new to this topic maybe I miss something. if the code is OK and there is a bug or this is not supported please let me know.
export class TaskTreeDataProvider implements vscode.TreeDataProvider<TreeItem> {
private _onDidChangeTreeData: vscode.EventEmitter<TreeItem | null> = new vscode.EventEmitter<TreeItem | null>();
readonly onDidChangeTreeData: vscode.Event<TreeItem | null> = this
._onDidChangeTreeData.event;
private eeake: Promise<TreeItem[]> | undefined = undefined;
private autoRefresh: boolean = true;
constructor(private context: vscode.ExtensionContext) {
this.autoRefresh = vscode.workspace
.getConfiguration(“sView")
.get("autorefresh");
let filePath = this.fileName;
let fileWatcher = vscode.workspace.createFileSystemWatcher(filePath);
fileWatcher.onDidChange(() => (this.eeake = this.getChildren()), this.refresh());
}
refresh(): void {
this._onDidChangeTreeData.fire();
}
public async getChildren(task?: TreeItem): Promise<TreeItem[]> {
let tasks = await vscode.tasks
.fetchTasks({ type: “run” })
.then(function (value) {
return value;
});
let entry: TreeItem[] = [];
if (tasks.length !== 0) {
for (var i = 0; i < tasks.length; i++) {
entry[i] = new TreeItem(
tasks[i].definition.type,
tasks[i].name,
{
command: “sView.executeTask",
title: "Execute",
arguments: [tasks[i]]
}
);
}
}
return entry;
}
getTreeItem(task: TreeItem): vscode.TreeItem {
return task;
}
}
class TreeItem extends vscode.TreeItem {
type: string;
constructor(
type: string,
label: string,
collapsibleState: vscode.TreeItemCollapsibleState,
command?: vscode.Command
) {
super(label, collapsibleState);
this.type = type;
this.command = command;
this.iconPath = getIcon();
}
}
If there is something missing please let me know and I add, I'm really stuck with it.
If there is another way to refresh the tree please let me know
Last line in constructor looks suspicious to me.
fileWatcher.onDidChange(() => (this.eeake = this.getChildren()), this.refresh());
I believe you mean:
fileWatcher.onDidChange(() => {
this.eeake = this.getChildren();
this.refresh();
});
Your original code actually immediately invokes this.refresh() in constructor and pass the return value as the 2nd arg to fileWatcher.onDidChange(). this.refresh() wasn't part of the listener passed as 1st arg to onDidChange().
First I have the following code section:
export default class Recipe {
constructor(recID) {
this.RecipeID = recID;
}
async GetRecipe() {
try {
let Result = await Axios(
`https://forkify-api.herokuapp.com/api/get?rId=${this.RecipeID}`
);
this.Tilte = Result.data.recipe.title;
this.Author = Result.data.recipe.publisher;
this.Image = Result.data.recipe.image_url;
this.Url = Result.data.recipe.source_url;
this.Ingredients = Result.data.recipe.ingredients;
this.PublisherUrl = Result.data.recipe.publisher_url;
this.Rank = Result.data.recipe.social_rank;
} catch (error) {
alert(error);
}
}
CalculateTime() {
try {
this.Time = Math.ceil(this.Ingredients.length / 3) * 15; // error is here
} catch (error) {
console.log(this.RecipeID + ": Length Error->"+error);
}
}
}
Then I call the above code in a separate file like:
import Recipe from "./Recipe";
const RecipeController = async () => {
const ID = window.location.hash.replace("#", "");
if (ID) {
AppState.Recipe = new Recipe(ID);
try {
await AppState.Recipe.GetRecipe();
AppState.Recipe.CalculateTime();
console.log(AppState.Recipe);
} catch (error) {
alert(error);
}
}
};
Now as shown in the following image, that I do get the response of the request & promised is resolved plus there are elements in the 'ingredients' array but sometimes I still get the error "cannot read property 'length' of undefined" when I call the 'CalculateTime()' although the array is now defined and sometimes I don't get any error & it works perfectly fine.Why this random behavior? Even the IDs in the JSON response & the error I logged match i.e. 47746.
This is one reason why having too many try/catches can obscure the causes of errors, making debugging difficult. The problem can be reduced to the following:
class Recipe {
constructor(recID) {
this.RecipeID = recID;
}
async GetRecipe() {
let Result = await fetch(
`https://forkify-api.herokuapp.com/api/get?rId=47746`
).then(res => res.json());
console.log(Result); // <----- look at this log
this.Tilte = Result.data.recipe.title;
// on the above line, the error is thrown
// Cannot read property 'recipe' of undefined
}
}
const r = new Recipe();
r.GetRecipe();
See the log: your Result object does not have a .data property, so referencing Result.data.recipe throws an error. Try Result.recipe instead:
class Recipe {
constructor(recID) {
this.RecipeID = recID;
}
async GetRecipe() {
let Result = await fetch(
`https://forkify-api.herokuapp.com/api/get?rId=47746`
).then(res => res.json());
const { recipe } = Result;
this.Tilte = recipe.title;
this.Author = recipe.publisher;
this.Image = recipe.image_url;
this.Url = recipe.source_url;
this.Ingredients = recipe.ingredients;
this.PublisherUrl = recipe.publisher_url;
this.Rank = recipe.social_rank;
}
CalculateTime() {
this.Time = Math.ceil(this.Ingredients.length / 3) * 15; // error is here
console.log('got time', this.Time);
}
}
(async () => {
const r = new Recipe();
await r.GetRecipe();
r.CalculateTime();
})();
Unless you can actually handle an error at a particular point, it's usually good to allow the error to percolate upwards to the caller, so that the caller can see that there was an error, and handle it if it can. Consider changing your original code so that RecipeController (and only RecipeController) can see errors and deal with them - you can remove the try/catches from the Recipe.
Are you sure some of the responses are not missing ingredients? And calculateTime is always called after getRecipe?
I would add a condition or fallback to prevent errors, as in.
this.Time = Math.ceil((this.Ingredients || []).length / 3) * 15;
I would speculate that this "random" behavior can be related to asynchronous code. You need to ensure that the class has Ingredients in place before you calculate. I have a feeling that you should try changing your syntax to a Promise handling using .then() and .catch(), especially since you already use try/catch in your code. This approach will ensure proper resolution of Promise on axios request, and will eliminate "randomness", because you will have a better control over different stages of Promise processing.
let Result = await Axios(
`https://forkify-api.herokuapp.com/api/get?rId=${this.RecipeID}`
)
.then((data) => {
this.Tilte = data.data.recipe.title;
this.Author = data.data.recipe.publisher;
this.Image = data.data.recipe.image_url;
this.Url = data.data.recipe.source_url;
this.Ingredients = data.data.recipe.ingredients;
this.PublisherUrl = data.data.recipe.publisher_url;
this.Rank = data.data.recipe.social_rank;
this.Ingerdients = data.data.recipe.ingredient;
}
.catch((err) => {
console.log(err);
return null;
});
I am using this endpoint:
#PostMapping("graphql")
public ResponseEntity<Object> getResource(#RequestBody Object query) { // String query
ExecutionResult result;
if (query instanceof String) {
result = graphQL.execute(query.toString()); // if plain text
} else{
String queryString = ((HashMap) query).get("query").toString();
Object variables = ((HashMap) query).get("variables");
ExecutionInput input = ExecutionInput.newExecutionInput()
.query(queryString)
.variables((Map<String, Object>) variables) // "var1" -> "test1"
.build();
result = graphQL.execute(input);
}
return new ResponseEntity<Object>(result, HttpStatus.OK);
}
When i don't have variable it works fine:
query {
getItem(dictionaryType: "test1") {
code
name
description
}
}
When i add variable it starts to fail, see here:
query {
getItem(dictionaryType: $var1) {
code
name
description
}
}
In my schema i have defined the query section as followed:
type Query {
getItem(dictionaryType: String): TestEntity
}
In java code:
#Value("classpath:test.graphqls")
private Resource schemaResource;
private GraphQL graphQL;
#PostConstruct
private void loadSchema() throws IOException {
File schemaFile = schemaResource.getFile();
TypeDefinitionRegistry registry = new SchemaParser().parse(schemaFile);
RuntimeWiring wiring = buildWiring();
GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(registry, wiring);
graphQL = GraphQL.newGraphQL(schema).build();
}
private RuntimeWiring buildWiring() {
initializeFetchers();
return RuntimeWiring.newRuntimeWiring()
.type("Query", typeWriting -> typeWriting
.dataFetcher("getItem", dictionaryItemFetcher)
)
.build();
}
private void initializeFetchers() {
dictionaryItemFetcher = dataFetchingEnvironment ->
dictionaryService.getDictionaryItemsFirstAsString(dataFetchingEnvironment.getArgument("dictionaryType"));
}
Any variables used inside an operation must be declared as part of the operation definition, like this:
query OptionalButRecommendedQueryName ($var1: String) {
getItem(dictionaryType: $var1) {
code
name
description
}
}
This allows GraphQL to validate your variables against the provided type, and also validate that the variables are being used in place of the right inputs.
My Java code should return user login as a String, but on Javascript side I'm receiving a strange Resource object whose numbered attributes each contains one char.
Here is my Java code:
#PostMapping(path = "/account/reset_password/finish", produces = MediaType.TEXT_PLAIN_VALUE)
#Timed
public ResponseEntity<String> finishPasswordReset(#RequestBody KeyAndPasswordVM keyAndPassword) {
if (!checkPasswordLength(keyAndPassword.getNewPassword())) {
return new ResponseEntity<>("Incorrect password", HttpStatus.BAD_REQUEST);
}
return userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey()).map(
user -> new ResponseEntity<String>(user.getLogin(), HttpStatus.OK)).orElse(
new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
}
Javascript controller code:
Auth.resetPasswordFinish({key: $stateParams.key, newPassword: vm.resetAccount.password}).then(function (userLogin) {
vm.success = 'OK';
console.log("userLogin="+userLogin);
}).catch(function () {
vm.success = null;
vm.error = 'ERROR';
});
The console prints:
userLogin=[object Object]
which is not very interesting.
Inspecting the received object gives:
One can see that each char of the String is a numbered attribute of the Resource object.
Javascript Auth code:
function resetPasswordFinish (keyAndPassword, callback) {
var cb = callback || angular.noop;
return PasswordResetFinish.save(keyAndPassword, function (userLogin) {
return cb(userLogin);
}, function (err) {
return cb(err);
}).$promise;
}
This one is just passing the parameter to the callback function.
Do you know how to receive a plain String instead of this Resource object? I apologize if this is a trivial question.
I know that doing this will work in order to retrieve the user login:
var i = 0;
var userLoginToString = "";
while (typeof userLogin[String(i)] !== 'undefined') {
userLoginToString += String(userLogin[String(i)]);
i += 1;
}
however I don't think that this is the intended way to use this Resource object.
Good day, I am new to JavaScript/TypeScript and looking for generic solution to indicate that ajax callback has completed so that other code that depends on the outcome of callback can execute.
For example class Fee Calculator, it gets instantiated with a service type and method calculate fee is called in order to display a fee of the service for the customer to agree.
class FeeCalculator {
private cost: number = 0;
private serviceType: number = 0;
private jsonAjax: JsonAjax = null;
constructor(serviceType: number) {
this.serviceType = serviceType;
this.jsonAjax = new JsonAjax("/tmaMaster/JSONServlet");
}
public calculateFee(): void {
// First, get the cost of the service from DB
this.cost = this.getServiceCost();
// calculate the fee and display it
// Now, this code would still be executed even if the callback
// didn't complete and therefore this.cost = 0,
// fee will be calculated wrongly
var fee: number = this.calculateTheFee(cost);
alert(fee);
}
getServiceCost = () => {
// IntegerWrapper is not relevant to this problem - just a primitive wrapper
var cost: IntegerWrapper = new IntegerWrapper();
this.execute("getServiceCost", this.serviceType, cost, this.setServiceCost);
}
// This is the callback
setServiceCost = (cost: IntegerWrapper) => {
this.cost = IntegerWrapper.primitiveValue;
}
private getFeeForTheCost(cost: number): number {
return cost / 4;
}
execute(command: string, requestDto: any, responseDto: any, callback: (responseDto: any) => void) {
var commandObject: JsonCommand = new JsonCommand(command, requestDto);
this.jsonAjax.call(commandObject, responseDto, callback);
}
}
Will also include JsonAjax class:
import JsonExternalizable = require("./JsonExternalizable");
class JsonAjax {
private READY_STATUS_CODE = 4;
private url: string;
constructor(url: string) {
this.url = url;
}
private isCompleted(request: XMLHttpRequest) {
return request.readyState === this.READY_STATUS_CODE;
}
call(requestDto: any, responseDto: any, callback: (responseDto: JsonExternalizable) => any) {
// Create a request
var request = new XMLHttpRequest();
// Attach an event listener
request.onreadystatechange = () => {
var completed = this.isCompleted(request);
if (completed && callback != null) {
/*
* N.B. PLease note that readFromJsonString returns void, therefore below line must be called sperately from line below.
*/
responseDto.readFromJsonString(request.responseText);
callback(responseDto);
}
};
// Specify the HTTP verb and URL
request.open('POST', this.url, true);
// Send the request
request.send(JSON.stringify(requestDto));
}
toString() {
return "JsonAjax";
}
}
export = JsonAjax;
The question is how do I make sure that calculateTheFee strictly called after getServiceCost is complete in other words make functions execute synchronously?
Ways I know of:
Do all other steps that require the cost value in a callback
itself. Not keen on that solution (what if there are more values
that need to be extracted from DB and all of them needed for
calculation) readability of that code will decrease.
Use timeout (Not generic enough, as we don't know how big is what we querying and how long it needs to "sleep")
P.S. Preferably without using extra libraries and plugins (company requirement)