cannot change observable from try catch block in mobx strict mode - mobx

class Someclass {
#observable waiting = false;
#observable error = null;
#action.bound
async authenticate({login, password}) {
try {
this.waiting = true;
const res = await myService.authenticate(login, password);
} catch (error) {
this.error = error; // Gives an error: Invariant Failed
} finally {
this.waiting = false; // Gives an error: Invariant Failed
// I've tried doing this too
// action(() => {
// this.waiting = false;
// })
}
}
}
In above example altering values from catch and finally block gives an error or warning Invariant Failed with strict mode. What is the correct way ?

Inside of async function we must wrap a function inside runInAction utility method for mutating #observable in strict mode. Example.
class Someclass {
#observable waiting = false;
#observable error = null;
#action.bound
async authenticate({login, password}) {
try {
this.waiting = true;
const res = await myService.authenticate(login, password);
} catch (error) {
runInAction(() => {
this.error = error;
});
} finally {
runInAction(() => {
this.waiting = false;
});
}
}
}
View this related issue on github

Related

How to throw an error in nextjs (server) if the method is GET and supported but no parameter is passed?

export default function handler(req, res {
const {
method,
query: { pid },
} = req;
if (method === 'GET') {
if (pid) {
res.statusCode = 200;
res.end(`Post: ${pid}`);
} else {
try {
const error = 'No post id specified';
throw new Error(error);
} catch (err) {
res.statusCode = 400;
res.end(`error: ${err}`);
}
}
} else {
const error = `unsupported method ${method}`;
try {
throw new Error(error);
} catch (err) {
res.statusCode = 400;
res.end(`error: ${err}`);
}
}
}
If the route /posts/ is called (without specifying pid), the above will return the 404 page's HTML but not the intended error "No post id specified"
The unsupported route if-branch works correctly instead.
How to obtain the above-explained behavior?
Like this:
const Page = ({ error, pid }) => {
if(error) return <p>{error}</p>
return <p>The following Page ID was passed {pid}</p>
}
export async function getServerSideProps(context) {
const { pid } = context.query;
if(!pid || typeof pid === 'undefined'){
return {
props { error: 'No pid passed' }
}
}
return {
props: { pid }
}
}
export default Page;
On the server side you can get the passed param from context.query the param needs to have the same name as the file in this case [pid].js
Then you simply check if the param is null or undefined. If so you return an error to message in the props to the component. Otherwise you return the PID or do a server side fetch and return the data to the component.

js-IPFS / vue.js upload error - Object is not async iterable

I have been working on js-ipfs (0.49.0) and this was working fine but I started getting some issues, anyway I have finally come back to look at the code again and the connection works fine but when I attempt to upload I get a new error
Object is not async iterable
I am not sure what that means or how to address in my code a lot of the examples are for react and not vue
Any pointers much appiciated.
methods: {
async getIpfsNodeInfo() {
try {
// Await for ipfs node instance.
node = await ipfs
// console.log(node)
// Call ipfs `id` method.
// Returns the identity of the Peer.
const { agentVersion, id } = await node.id()
this.agentVersion = agentVersion
this.id = id
// Set successful status text.
this.status = 'Connected to IPFS 😊'
} catch (err) {
// Set error status text.
this.status = `Error: ${err}`
}
},
onFileSelected(event) {
this.selectedFile = event.target.files[0]
this.saveIPFS()
},
async saveIPFS() {
try {
for await (const result of node.add(this.selectedFile)) {
this.fileContents = result
this.getIPFS()
}
} catch (err) {
// Set error status text.
this.status = `Error: ${err}`
}
},
ipfs.add returns a single object since ipfs#0.48.0 - you need to change:
async saveIPFS() {
try {
for await (const result of node.add(this.selectedFile)) {
this.fileContents = result
this.getIPFS()
}
} catch (err) {
// Set error status text.
this.status = `Error: ${err}`
}
},
to:
async saveIPFS() {
try {
this.fileContents = await node.add(this.selectedFile)
this.getIPFS()
} catch (err) {
// Set error status text.
this.status = `Error: ${err}`
}
},
See the blog post for more: https://blog.ipfs.io/2020-07-20-js-ipfs-0-48/#ipfs-add

I am getting `Can not use keyword 'await' outside of a async function` within an Async function.. React-native

I am having an issue with async await for my AsyncStorage function within my React-native application. The error I'm getting is:
Can not use keyword 'await' outside of a async function
As you can see below, it's obvious that await is within the function. What am I doing wrong to get this error?
_retrieveData = async function (location) {
try {
var index = await AsyncStorage.getItem(location, (err, result) => result).then(result => result).catch(error=>console.log(error))
if (index !== null) {
return JSON.parse(index)
}
} catch (error) {
return null
}
};
_storeData = async function(location, value) {
try {
await AsyncStorage.set(location, JSON.stringify(value));
} catch (error) {
console.log(error)
}
};
Use ES6 arrow functions
const _retrieveData = async location => {
try {
let index = await AsyncStorage.getItem(location)
if (index !== null) {
return JSON.parse(index);
}
} catch (error) {
return null;
}
};
const _storeData = async (location, value) => {
try {
await AsyncStorage.set(location, JSON.stringify(value));
} catch (error) {
console.log(error);
}
};
Make them as an arrow functions
_retrieveData = async location => {
try {
let index = await AsyncStorage.getItem(location)
if (index !== null) {
return JSON.parse(index);
}
} catch (error) {
return null;
}
};
_storeData = async (location, value) => {
try {
await AsyncStorage.set(location, JSON.stringify(value));
} catch (error) {
console.log(error);
}
};

apollo-server-express, graphql custom schema directive

This is weird for me.
According this document i made my Auth SchemaDirective like this:
class RequireAuthDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const { resolve = defaultFieldResolver } = field;
field.resolve = async (...args) => {
let [, params, { req, res, connection }] = args;
let { user } = req || connection.context;
if (!!user) {
return await resolve.apply(this, args);
} else {
throw new AuthenticationError('You must be signed in to view this resource.');
}
};
}
}
This works fine in every Query, Mutation, Subscription
But when i use an external async method to check authorization like this:
class RequireAuthDirective extends SchemaDirectiveVisitor {
visitFieldDefinition(field) {
const { resolve = defaultFieldResolver } = field;
field.resolve = async (...args) => {
let [, params, { req, res, connection }] = args;
let { user } = req || connection.context;
if (!!user) {
if (await isAllowed(user.id, field.name, params)) return await resolve.apply(this, args); // ChkPoint
throw new AuthenticationError('You are not authorized to access this resource.');
} else {
throw new AuthenticationError('You must be signed in to access this resource.');
}
};
}
}
This works fine in Queries and Mutations but not in subscriptions!
Note: if i remove the ChkPoint condition ( Which is returning true ) it will works in subscription.

How to prevent multi beginTransactions in Realmjs?

I create a function to handle transaction, then I call it to multi places. I got crash when another transaction not yet complete when I open new transaction.
Here my code:
const RealmMakeTransaction = async (action) => {
try {
realm.GetInstance().beginTransaction();
let response = await action();
realm.GetInstance().commitTransaction();
return response;
} catch (e) {
realm.GetInstance().cancelTransaction();
}
};
You can easily check if realm is already in transaction or not before calling beginTransaction() by calling realm.GetInstance().isInTransaction
Your code will look like :
const RealmMakeTransaction = async (action) => {
//use single instance
let realm = realm.GetInstance();
try {
if( realm.isInTransaction)
realm.cancelTransaction();
realm.beginTransaction();
let response = await action();
realm.commitTransaction();
return response;
} catch (e) {
realm.cancelTransaction();
realm.close();
}
};