How to timeout a timer instead of cancelling [duplicate] - timer

How would you wait for future response for a specific amount of time?
Say, we make a http post request and await for its response before we close the http request, but, we wait for only 3 secs, else we close the request.
How would you achieve that?
Something like
Future makePostReq() async{
....
await http response for 3 secs
....
if(response) {
... Do something with it
}
Http.close
}

You can use Future.any constructor to make a race condition
final result = await Future.any([
Future.value(42),
Future.delayed(const Duration(seconds: 3))
]);
You can also use Future.timeout method
final result = await Future.value(42).timeout(const Duration(seconds: 3));

You can do it very easily
try {
var response = await Http.get("YourUrl").timeout(const Duration(seconds: 3));
if(response.statusCode == 200){
print("Success");
}else{
print("Something wrong");
}
} on TimeoutException catch (e) {
print('Timeout');
} on Error catch (e) {
print('Error: $e');
}
This example sets timeout to 3 second. If it has been 3 seconds and no response received, it will throw TimeoutException
Import this :
import 'package:http/http.dart' as Http;
import 'dart:async';

Future.any([asyncfunc, ...])
Here's an example of using Remi's Future.any solution where the future that returns first, will be used. The other is discarded.
So, the first future is your data-gathering/slow function and the other is a fallback when your call is taking too long.
dynamic result = await Future.any([
getData(fakeDelay: seconds), // ← hope this returns first
timeoutAfter(sec: timeout, onTimeout: () => 'Timed Out!', ) // ← waited too long, do this
]);
Example in Flutter Page
Here's a copy/paste example for a Flutter page:
(look at your debug/run output window for messages)
import 'package:flutter/material.dart';
class FutureTimeoutPage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Future or Timeout Page'),
),
body: FutureAnyExample(),
);
}
}
class FutureAnyExample extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Complete before timeout or timeout:'),
SizedBox(height: 30,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(onPressed: () => getDataOrTimeout(seconds: 1, timeout: 3),
child: Text('In Time')),
ElevatedButton(onPressed: () => getDataOrTimeout(seconds: 5, timeout: 3),
child: Text('Too Slow'))
],
)
],
);
}
Future<void> getDataOrTimeout({int seconds, int timeout}) async {
/// In Future.any, put as many async functions as you need.
/// Whichever completes first, will be returned. All others are discarded
dynamic result = await Future.any([
getData(fakeDelay: seconds), // ← hope this returns first
timeoutAfter(sec: timeout, onTimeout: () => 'Timed Out!', ) // ← waited too long, do this
]);
print(result);
}
/// Mock of a long-running operation like getting DB data, or API call
Future<String> getData({int fakeDelay}) async {
return Future.delayed(Duration(seconds: fakeDelay), () => 'Data returned!');
}
/// Do this in case my long-running op takes too long
/// Can run a function or just return some message
Future<dynamic> timeoutAfter({int sec, Function() onTimeout}) async {
return Future.delayed(Duration(seconds: sec), onTimeout);
}
}

Related

Flutter does not output all the results during a post request

Flutter does not output all the results during a post request. Out of about 260 comes to the list, 113 are saved.
...............................................................................................................................................................................................................
Future<List<NewChatModel>> getAllChats({#required String userId}) async {
final response = await http.post(
Uri.parse(URL),
headers: <String, String>{
'Content-Type': 'application/json; charset=UTF-8',
},
body: jsonEncode(<String, int>{
'first_user_id': int.parse(userId),
}),
);
if (response.statusCode == 200) {
List<NewChatModel> returnList = [];
for (var i in jsonDecode(response.body)) {
returnList.add(NewChatModel.fromJson(i));
}
print(returnList.length);
return returnList;
} else {
return null;
}
}
class NewChatModel {
String id;
String chatId;
String messageId;
String message;
String messageDate;
String schoolId;
String fullName;
String phone;
String email;
String urlProfileImage;
String birthday;
String roleId;
String lastActivity;
String isOnline;
NewChatModel(
{this.id,
this.chatId,
this.messageId,
this.message,
this.messageDate,
this.schoolId,
this.fullName,
this.phone,
this.email,
this.urlProfileImage,
this.birthday,
this.roleId,
this.lastActivity,
this.isOnline});
factory NewChatModel.fromJson(dynamic json) {
return NewChatModel(
id: json['id'].toString(),
chatId: json['chat_id'].toString(),
messageId: json['message_id'].toString(),
message: json['message'].toString(),
messageDate: json['message_date'].toString(),
schoolId: json['school_id'].toString(),
fullName: json['full_name'].toString(),
phone: json['phone'].toString(),
email: json['email'].toString(),
urlProfileImage: json['urlProfileImage'].toString(),
birthday: json['birthday'].toString(),
roleId: json['role_id'].toString(),
lastActivity: json['last_activity'].toString(),
isOnline: json['is_online'].toString(),
);
}
}
Edit: added NewChatModel code
But I don`t think that its help solve problem
I think problem in String limit, idk
If at all it helps you, I have a list of chat conversations in my app, too. I collect them with a Stream and display them with a StreamBuilder(). This is a very resource efficient way to do it, without the need to actually collect all the conversations at once! The StreamBuilder() widget makes sure it collects only the conversations that are currently visible on the screen (plus some).
This is what it looks like:
import 'package:my_giggz/firebase_labels.dart';
import 'package:my_giggz/my_firebase.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
class MyMessagesScreen extends StatefulWidget {
#override
_MyMessagesScreenState createState() {
return _MyMessagesScreenState();
}
}
class _MyMessagesScreenState extends State<MyMessagesScreen> {
String myUid = MyFirebase.authObject.currentUser!.uid;
#override
Widget build(BuildContext context) {
return Scaffold(
body: StreamBuilder<QuerySnapshot>(
// Stream of all the conversations in the database that contain my uid:
stream: MyFirebase.storeObject.collection(kCollectionConversations).where(kFieldParticipantsArray, arrayContains: myUid).orderBy(kFieldLastTimeStamp, descending: true).snapshots(),
builder: (context, asyncSnapshot) {
List<Widget> convCards = [];
QuerySnapshot? foundConversations = asyncSnapshot.data;
if (foundConversations != null) {
//It always wants to be null at first, and then I get errors for calling on null.
for (QueryDocumentSnapshot conv in foundConversations.docs) {
Map<String, dynamic> convData = conv.data() as Map<String, dynamic>;
convCards.add(
ConvCard(convData) // A homemade widget that takes a Map argument to display some data from the conversation
);
// i++;
}
} else {
// For as long as the found conversations are null, a spinner will be shown:
return Center(child: CircularProgressIndicator());
}
// This part will only be reached if conversations were found:
return ListView.builder(
padding: EdgeInsets.all(0),
itemCount: convCards.length,
itemBuilder: (context, index) {
return convCards[index];
},
);
},
),
);
}
}
If you have any questions on that, I'm happy to answer.
I do not know why this is so, but here is the answer to my question :)
For some reason, he doesn't want to show the entire length of the list, but he filled it out absolutely correctly)

Flutter: How to pass array data from json Future< to Widget

Being new to flutter, I'm learning and stumbling on the go.
I am trying to pass an array that I have received from json into an already waiting widget structure but can't quite seem to get the connection.
Here's the sample code:
class Products extends StatefulWidget {
#override
_ProductsState createState() => _ProductsState();
}
class _ProductsState extends State<Products> {
#override
void initState() {
_getProducts();
}
Future<List<Single_prod>> _getProducts() async {
var url = "";
var data = await http.get(url);
var jsonData = json.decode(data.body) as Map<String, dynamic>;
//print(jsonData.toString());
//jsonData.forEach((k, v) => print("Key : $k, Value : $v"));
List<Single_prod> items = [];
jsonData.forEach((k, v){
Single_prod item = Single_prod(v["error"], v["id"], v["name"], v["price"], v["image"]);
items.add(item);
});
//print(items.length);
return items; <---Tring to pass this to Widget build but not recognized.....
}
#override
Widget build(BuildContext context) {
return GridView.builder(
itemCount: items.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index){
return Single_prod(
prod_err: items[index]['error'], <--- This items array is not recognized
prod_id: items[index]['id'],
prod_name: items[index]['name'],
prod_price: items[index]['price'],
prod_image: items[index]['image'],
);
});
}
}
The items array is not recognized in the widget
Here is the rest of the code:
class Single_prod extends StatelessWidget {
final prod_err;
final prod_id;
final prod_name;
final prod_price;
final prod_image;
Single_prod({
this.prod_err,
this.prod_id,
this.prod_name,
this.prod_price,
this.prod_image,
});
#override
Widget build(BuildContext context) {
return Card(
child: Hero(
tag: prod_name,
child: Material(
child: InkWell(
onTap: () => Navigator.of(context).push(new MaterialPageRoute(
// here we are passing the values of the products to the details page
builder: (context) => new ProductDetails(
prod_detail_name: prod_name,
prod_detail_image: prod_image,
prod_detail_id: prod_id,
prod_detail_price: prod_price,
))),
child: GridTile(
footer: Container(
height: 40.0,
color: Colors.white70,
child: ListTile(
leading: Text(prod_name, style: TextStyle(fontWeight: FontWeight.bold),),
title: Text(
prod_price,
style: TextStyle(color: Colors.blue, fontWeight: FontWeight.w800, fontSize: 12),
),
/*subtitle: Text(
prod_oldprice,
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w800, fontSize: 11, decoration: TextDecoration.lineThrough),
),*/
),
),
child: Image.asset(prod_image,
fit: BoxFit.cover,),
),
),
),
),
);
}
}
How does the upper code connect with the lower code?
Thanks in advance.
First, look at the scope of your 'items' variable: it is defined in getItems() function, and it is not visible outside the function. So, first thing: make it class level property.
Next - your initState will call your method. Method is async, and the way to handle it in initState to use '.then' on the Future returned by your method. What you want to do here is: once the future completes, you want to set your class level variable to hold the value returned by _getProduct() function.
And finally - this is very important to understand: you don't call build method yourself - flutter framework does it for you. Now, flutter does not have a magic way of knowing when you changed the data - it won't observe your code, so you need to tell it somehow that your state object changed, and it requires rebuild. You do it by calling setState() function.
I think you have another issue here actually: you already bulit your Single_prod widget in _getProduct(), no need to build it again. I tried to correct this also.
Try this (I didn't compile it so it might have few errors):
class Products extends StatefulWidget {
#override
_ProductsState createState() => _ProductsState();
}
class _ProductsState extends State<Products> {
List<Single_prod> items = [];
#override
void initState() {
super.initState();
_getProducts().then( (result) {
setState(() {
items=result;
}
});
}
Future<List<Single_prod>> _getProducts() async {
var url = "";
var data = await http.get(url);
var jsonData = json.decode(data.body) as Map<String, dynamic>;
//print(jsonData.toString());
//jsonData.forEach((k, v) => print("Key : $k, Value : $v"));
List<Single_prod> items = [];
jsonData.forEach((k, v){
Single_prod item = Single_prod(v["error"], v["id"], v["name"], v["price"], v["image"]);
items.add(item);
});
//print(items.length);
return items;
}
#override
Widget build(BuildContext context) {
return GridView.builder(
itemCount: items.length,
gridDelegate: new SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
itemBuilder: (BuildContext context, int index){
return items[index];
});
}
}

Flutter firebase, how to retrive user data and have it on the map or a list

I saw many examples on internet, but in each case, the data is returning on a listview. I don't want to print in a listview. I want to use data in the app.
This is the way I am addind data on firebase. (I am using a class Info).
void infouser(context) async {
final db = FirebaseFirestore.instance;
final info = Info(yourname, animaName, yourmail);
final uid = await Provider.of(context).auth.getCurrentUID();
await db.collection("userData").doc(uid).collection("info").add(info.toJson());
}
I also tried with set,
createInfo(context) async {
final uid = await Provider.of(context).auth.getCurrentUID();
DocumentReference documentReference =
await FirebaseFirestore.instance.collection('Animal').doc(uid);
Map<String, dynamic> todos = {
'name': yourname,
'animalname' :animalName,
'email' : yourmail,
};
documentReference.set(todos).whenComplete(() {
print( yourname, animalName, yourmail
);
});
}
In both case, I was only able to print data on a Listview. But that is not what I want. I want to have data on a list or a map to be able to use it elsewhere in the app.
Please, I if you have a link(or give me a example of code) where I can see example, it will be appreciate.
thank you.
This is the example of retrieving data as map from firestore:
class GetUserName extends StatelessWidget {
final String documentId;
GetUserName(this.documentId);
#override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('users');
return FutureBuilder<DocumentSnapshot>(
future: users.doc(documentId).get(),
builder:
(BuildContext context, AsyncSnapshot<DocumentSnapshot> snapshot) {
if (snapshot.hasError) {
return Text("Something went wrong");
}
if (snapshot.connectionState == ConnectionState.done) {
Map<String, dynamic> data = snapshot.data.data();
return Text("Full Name: ${data['full_name']} ${data['last_name']}");
}
return Text("loading");
},
);
}
}
I advise to use https://firebase.flutter.dev/docs/firestore/usage/? documentation when working with Firebase from flutter

Get Message From Kafka, send to Rsocket and Receive it from React client

I am trying to send data from kafka using Spring cloud stream to Rsocket and then represent data on React
Here is my configuration.
#Configuration
public class RsocketConsumerConfiguration {
#Bean
public Sinks.Many<Data> sender(){
return Sinks.many().multicast().directBestEffort();
}
}
#Controller
public class ServerController {
#Autowired
private Sinks.Many<Data> integer;
#MessageMapping("integer")
public Flux<Data> integer() {
return integer.asFlux();
}
#EnableBinding(IClientProcessor.class)
public class Listener {
#Autowired
private Sinks.Many<Data> integer;
#StreamListener(IClientProcessor.INTEGER)
public void integer(Data val) {
System.out.println(val);
integer.tryEmitNext(val);
}
}
let client = new RSocketClient({
transport: new RSocketWebSocketClient(
{
url: 'ws://localhost:7000/ws',
wsCreator: (url) => new WebSocket(url),
debug: true,
},
BufferEncoders,
),
setup: {
dataMimeType: "application/json",
metadataMimeType: MESSAGE_RSOCKET_COMPOSITE_METADATA.string,
keepAlive: 5000,
lifetime: 60000,
},
});
client
.then(rsocket => {
console.log("Connected to rsocket");
rsocket.requestStream({
metadata: Buffer.from(encodeCompositeMetadata([
[MESSAGE_RSOCKET_ROUTING, encodeRoute("integer")],
])),
})
.subscribe({
onSubscribe: s => {
s.request(2147483647)
},
onNext: (p) => {
let newData = {
time: new Date(JSON.parse(p.data).time).getUTCSeconds(),
integer: JSON.parse(p.data).integer
}
newData.integer >100?setInteger(currentData => [newData, ...currentData]):setInt(currentData => [newData, ...currentData])
console.log(newData)
},
onError: (e) => console.error(e),
onComplete: () => console.log("Done")
});
spring.cloud.stream.bindings.integer.destination=integer
Not able to see it in react app. Please advise. What I am doing wrong?
Given the data appears to be going directly from Kafka (via Spring) to the client, perhaps it would make more sense to stream Kafka messages via an internet-messaging broker to Internet-facing clients over WebSockets.
Disclosure: I am not the author of that article, but do work at that company where the author works. We see this use case frequently, so expect this approach may be useful.

JSON http.get return áá flutter

I am trying to retrieve a JSON from a URL link. The JSON data consist of both English and Burmese language. However, when I retrieve the data, the app shows a bunch of Burmese words converted into "áá". Any solutions?
class _GetJsonResultState extends State<GetJsonResult> {
#override
Widget build(BuildContext context) {
var jsonFileName = "assets/resultlist/resultlist.json";
fetchData() async {
final response =
await http.get('https://jsonkeeper.com/b/47QP');
if (response.statusCode == 200) {
return(response.body);
}
}
return FutureBuilder(
future: fetchData(),
builder: (context, snapshot) {
List myData = json.decode(snapshot.data.toString());
if (myData == null) {
return Scaffold(
body: Center(
// Loads upon null
child: CircularProgressIndicator(),
),
);
} else {
return Home(myData: myData);
}
},
);
}
}
This is what I'm supposed to get
Change your fetchData() function as below
fetchData() async {
final response = await http.get('https://jsonkeeper.com/b/47QP',
headers: {"charset": "utf-8", "Accept-Charset": "utf-8"});
if (response.statusCode == 200) {
return (utf8.decode(response.bodyBytes));
}
}
Its a decoding issue. Just to clarify what is happening in background
The Dart http API defines (as mentioned below) two ways of interacting with the response data:
body → String
The body of the response as a string. This is converted from bodyBytes using the charset parameter of the Content-Type header field, if available. If it's unavailable or if the encoding name is unknown, latin1 is used by default, as per RFC 2616.
bodyBytes → Uint8List
The bytes comprising the body of this response.
More details at https://github.com/dart-lang/http/issues/175#issuecomment-415721621
So in such cases where you know encoding before hand and think its going to mess use request encoding and a decode from byte
fetchData() async {
final response = await http.get('https://jsonkeeper.com/b/47QP',
headers: {"charset": "utf-8", "Accept-Charset": "utf-8"});
if (response.statusCode == 200) {
return (utf8.decode(response.bodyBytes));
}
}

Resources