Flutter objectbox limit - flutter

a have a question, I need to apply limit in the messages array but I do khow can I do it.
static Stream<Room?> listenChatRoom(int roomId) {
try {
var builder = objectBox.store
.box<RoomObjectBoxModel>()
.query(RoomObjectBoxModel_.id.equals(roomId));
builder.linkMany(RoomObjectBoxModel_.messages, RoomObjectBoxModel_.roomType.equals("chat"));
return builder.watch(triggerImmediately: true).transform(
StreamTransformer.fromHandlers(handleData: (query, sink) {
sink.add(query.findFirst()?.toDomain());
}),
);
} catch (ex) {
rethrow;
}
}

Related

Can a Future internally retry an http request if it fails in Flutter?

I'm using the following code to successfully poll mysite for JSON data and return that data. If the request fails, then it successfully returns an error message as well return Result.error(title:"No connection",msg:"Status code not 200", errorcode:0);.
What I'd like to happen is have the app retry the request 3 times before it returns the error message.
Basically have the future call itself for some number of iterations.
I did try to create an external function that would get called from the outer catch which then would in turn call the getJSONfromTheSite function a second and then a third time, but the problem was that you would have a non-null return from the Future so the app wouldn't accept that approach
Is there another way of doing this?
Future<Result> getJSONfromTheSite(String call) async {
debugPrint('Network Attempt by getJSONfromTheSite');
try {
final response = await http.get(Uri.parse('http://www.thesite.com/'));
if (response.statusCode == 200) {
return Result<AppData>.success(AppData.fromRawJson(response.body));
} else {
//return Result.error("Error","Status code not 200", 1);
return Result.error(title:"Error",msg:"Status code not 200", errorcode:1);
}
} catch (error) {
return Result.error(title:"No connection",msg:"Status code not 200", errorcode:0);
}
}
The following extension method will take a factory for futures, create them and try them until the retry limit is reached:
extension Retry<T> on Future<T> Function() {
Future<T> withRetries(int count) async {
while(true) {
try {
final future = this();
return await future;
}
catch (e) {
if(count > 0) {
count--;
}
else {
rethrow;
}
}
}
}
}
Assuming you have a rather plain dart method:
Future<AppData> getJSONfromTheSite(String call) async {
final response = await http.get(Uri.parse('http://www.thesite.com/'));
if (response.statusCode == 200) {
return AppData.fromRawJson(response.body);
} else {
throw Exception('Error');
}
}
You can now call it like this:
try {
final result = (() => getJSONfromTheSite('call data')).withRetries(3);
// succeeded at some point, "result" being the successful result
}
catch (e) {
// failed 3 times, the last error is in "e"
}
If you don't have a plain method that either succeeds or throws an exception, you will have to adjust the retry method to know when something is an error. Maybe use one of the more functional packages that have an Either type so you can figure out whether a return value is an error.
Inside catch() you can count how many times have you retried, if counter is less than three you return the same getJSONfromTheSite() function, but with the summed counter. And if the connection keeps failing on try{} and the counter is greater than three it will then returns the error.
Future<Result> getJSONfromTheSite(String call, {counter = 0}) async {
debugPrint('Network Attempt by getJSONfromTheSite');
try {
String? body = await tryGet();
if (body != null) {
return Result<AppData>.success(AppData.fromRawJson(response.body));
} else {
//return Result.error("Error","Status code not 200", 1);
return Result.error(title:"Error",msg:"Status code not 200", errorcode:1);
}
} catch (error) {
if(counter < 3) {
counter += 1;
return getJSONfromTheSite(call, counter: counter);
} else {
return Result.error(title:"No connection",msg:"Status code not 200", errorcode:0);
}
}
}

Flutter how to handle errors in async / await

I want to catch an exception if the app fails to connect to the server (If the server is turned off for example) but not sure how and didn't succeed so far.
My code:
static Future<String> communicate(String img, String size) async
{    
String request = size.padLeft(10, '0') + img;
Socket _socket;
    await Socket.connect(ip, 9933).then((Socket sock)
{
_socket = sock;
    }).then((_)
{
//Send to server
_socket.add(ascii.encode(request));
return _socket.first;
    }).then((data)
{
//Get answer from server
response =  ascii.decode(base64.decode(new String.fromCharCodes(data).trim()));
});
    return response;    
}
Function call:
var ans = await communicate(bs64Image, size);
In general, you handle errors like this with async/await:
try {
// code that might throw an exception
}
on Exception1 {
// exception handling code
}
catch Exception2 {
// exception handling
}
finally {
// code that should always execute; irrespective of the exception
}
In your case, you should try something like:
try {
var ans = await communicate(bs64Image, size);
}
catch (e){
print(e.error);
}
finally {
print("finished with exceptions");
}
Try using SocketException if request fails exception will be thrown
import 'dart:io';
try {
response = await get(url);
} on SocketException catch (e) {
return e;
}

After updating to ionic 5 and Angular 9 , error TS2698: Spread types may only be created from object types

After updating to Ionic 5 and Angular 9, I get the following error:
error TS2698: Spread types may only be created from object types.
ERROR in src/app/providers/firestore-db.service.ts:19:13 - error
TS2698: Spread types may only be created from object types. [ng] 19
...doc.payload.doc.data()
This is the related code:
import { Injectable } from '#angular/core';
import { AngularFirestore } from '#angular/fire/firestore';
import { map } from 'rxjs/operators';
#Injectable({
providedIn: 'root'
})
export class FirestoreDbService {
constructor(private db: AngularFirestore) { }
getAllData(collectionId) {
/* return this.db.collection('product').valueChanges(); */
return this.db.collection(collectionId).snapshotChanges().pipe(
map(docArray => {
return docArray.map(doc => {
return {
id: doc.payload.doc.id,
...doc.payload.doc.data()
}
})
})
)
}
async insertData(collectionId, data) {
try {
const result = await this.db.collection(collectionId).add(data);
return result;
} catch (error) {
throw new Error(error);
}
}
async getDataById(collectionId, docId) {
try {
const result = await this.db.collection(collectionId).doc(docId).ref.get();
if (result.exists) {
return result.data();
} else {
throw new Error('Data not found with given id');
}
} catch (error) {
throw new Error(error);
}
}
async updateData(collectionId, docId, updatedData) {
try {
const result = await this.db.doc(`${collectionId}/${docId}`).update(updatedData);
return result;
} catch (error) {
throw new Error(error);
}
}
async deleteData(collectionId, docId) {
try {
const result = await this.db.doc(`${collectionId}/${docId}`).delete();
return result;
} catch (error) {
throw new Error(error);
}
}
}
I solved the issue by downgrading typescript from 3.7.5 to 3.6.4
npm install typescript#3.6.4
and make sure it is also 3.6.4 in the package.json

jasmine: Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.. When i am trying get a non present element

When I am trying to check presence of not presented element/ button. I am getting:
Jasmine timeout exception
My code like
getName(): any {
let name = element(by.id("xxxxxx"));
return name.isPresent().then((ispresent) => {
if (ispresent) {
return name.getText();
} else {
return '';
}
})
}
I am trying to access that method expect(method).toequal('');
It should run, because if not present i am expecting empty string but i am getting Jasmine timeout.. I didn't added any waits any where.
isPresent()
From the GitHub repo, ElementFinder.isPresent
isPresent(): wdpromise.Promise<boolean> {
return this.count().then((count) => {
return count > 0;
});
}
isPresent checks for a count, but does not catch if there is an error. If the count throws, we should probably return 0. Getting a text for an element that does not exist should also have throw a promise rejection.
Note: It might be better to change your method to async / await (optional).
async getName(): webdriver.promise.Promise<string> {
const name = element(by.id("xxxxxx"));
try {
return name.getText();
} catch (e) {
return '';
}
}
Or not async / await
getName(): webdriver.promise.Promise<string> {
const name = element(by.id("xxxxxx"));
return name.getText().catch(e) {
return '';
}
}
Try the below one
async getName() {
let name = element(by.id("xxxxxx"));
let value: string = '';
await name.ispresent().then((ispresent) => {
if (ispresent) {
value=name.getText();
}
});
return value;
}
Hope it helps you

Using design documents in pouchDB with crypto-pouch

After testing pouchDB for my Ionic project, I tried to encrypt my data with crypto-pouch. But I have a problem with using design documents. I used the following code:
One of my design documents:
var allTypeOne = {
_id: '_design/all_TypeOne',
views: {
'alle_TypeOne': {
map: function (doc) {
if (doc.type === 'type_one') {
emit(doc._id);
}
}.toString()
}
}
};
For init my database:
function initDB() {
_db = new PouchDB('myDatabase', {adapter: 'websql'});
if (!_db.adapter) {
_db = new PouchDB('myDatabase');
}
return _db.crypto(password)
.then(function(){
return _db;
});
// add a design document
_db.put(allTypeOne).then(function (info) {
}).catch(function (err) {
}
}
To get all documents of type_one:
function getAllData {
if (!_data) {
return $q.when(_db.query('all_TypeOne', { include_docs: true}))
.then(function(docs) {
_data = docs.rows.map(function(row) {
return row.doc;
});
_db.changes({ live: true, since: 'now', include_docs: true})
.on('change', onDatabaseChange);
return _data;
});
} else {
return $q.when(_data);
}
}
This code works without using crypto-pouch well, but if I insert the _db.crypto(...) no data is shown in my list. Can anyone help me? Thanks in advance!
I'm guessing that your put is happening before the call to crypto has finished. Remember, javascript is asynchronous. So wait for the crypto call to finish before putting your design doc. And then use a callback to access your database after it's all finished. Something like the following:
function initDB(options) {
_db = new PouchDB('myDatabase', {adapter: 'websql'});
if (!_db.adapter) {
_db = new PouchDB('myDatabase');
}
_db.crypto(password)
.then(function(){
// add a design document
_db.put(allTypeOne).then(function (info) {
options.success(_db);
})
.catch(function (err) { console.error(err); options.error(err)})
.catch(function (err) { console.error(err); options.error(err);})
}
}
initDB({
success:function(db){
db.query....
}
)