Return String from Future Object - string

I am trying to fetch html page via localproxy to parse and get urls from it. I can't find any library which works without Future in Dart. So i have difficulty returning String from a Future Object. Below is full code of dart file.
import 'package:universal_html/driver.dart';
import 'package:universal_html/prefer_universal/html.dart';
String proxyUrl='http://localhost/php-proxy/index.php?q=';
String hallTicketUrl='http://www.ignou.ac.in/ignou/studentzone/results/6';
Future<String> getList()async{
final driver = HtmlDriver();
await driver.setDocumentFromUri(Uri.parse(proxyUrl+hallTicketUrl));
final items = driver.document.querySelectorAll('.middleconten2column a');
Element urls=Element.tag('urls');
items.forEach((item)=>urls.append(Element.tag('url')
..setAttribute('href',item.getAttribute('href'))
..text=item.text
)
);
print('${items.length} items found');
return Future.value(urls.outerHtml);
}
String Handler(String app){
switch(app){
case 'list': return getList() as String;
}
return "";
}
main(){
print(Handler('list'));
}

I think you have misunderstood what the async keyword does to methods. When a method are marked as async it will always automatically returns a Future of something. That is the reason why you need to specify e.g. Future<String> as the return type.
But because the creation are done "automatically" you don't really need to do the following:
return Future.value(urls.outerHtml);
But can just do:
return urls.outerHtml;
After this your have discovered the problem with using asynchronous programming where everything in your call stack needs to be marked as async since you have an await somewhere in your code.
I have fixed your code so it now hope it works correctly with all the future stuff:
import 'package:universal_html/driver.dart';
import 'package:universal_html/prefer_universal/html.dart';
String proxyUrl = 'http://localhost/php-proxy/index.php?q=';
String hallTicketUrl = 'http://www.ignou.ac.in/ignou/studentzone/results/6';
Future<String> getList() async {
final driver = HtmlDriver();
await driver.setDocumentFromUri(Uri.parse(proxyUrl + hallTicketUrl));
final items = driver.document.querySelectorAll('.middleconten2column a');
Element urls = Element.tag('urls');
items.forEach((item) => urls.append(Element.tag('url')
..setAttribute('href', item.getAttribute('href'))
..text = item.text));
print('${items.length} items found');
return urls.outerHtml;
}
Future<String> Handler(String app) async {
switch (app) {
case 'list':
return await getList();
}
return "";
}
main() async {
print(await Handler('list'));
}

Related

Value returning from an async function is not the actual value

I'm calling an async function that has the file path as a parameter and reads and displays the content in the file.
this is the place where I'm invoking the function.
this is the function.
After reading the contents in the file, the data is printed in the console.
But when I try to use the same value to display in the emulator I'm getting error.
Why actual string value is not returned from the function??
error.
readContent is a future method, you need to wait to complete the fetching.
For future method, try using FutureBuilder.
late Future future = readContent();
#override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
builder: (context, snapshot) {
if (snapshot.hasData) {
return Text("${snapshot.data}");
}
return CircularProgressIndicator();
},
),
);
}
Find more about using FutureBuilder.
An async function in dart can only return a Future.
Your readContent function signature doesn't declare a return value:
readContent(String path) async {
var result = await File(path).readAsString();
print(result);
return result
}
If you explicitly declare the return value as String you'll get a compilation error. Async methods can only return a future:
Future<String> readContent(String path) async {
var result = await File(path).readAsString();
print(result);
return result
}
The await keyword allows you to access the value returned by a Future, it is not the same as calling the function synchronously.
The only reason you need the await keyword in your code is because you're printing the value to console when the Future completes. You could do this instead, which is the same function without printing to console and without async await.
readContent(String path) {
return File(path).readAsString();
}
To address the issue described in your question, you might call readAsString synchronously:
readContent(String path) {
return File(path).readAsStringSync();
}
Or use await on the calling side
var val = await readContent(path);
Or
var txt = "";
readContent(path).then((value) {
txt = value;
setState(() {});
});
Or use the FutureBuilder widget

Get text from ".txt" file and save it in String variable dart

I have a ".txt" file called "bio.txt" inside the Document folder of my application.
I want to read its content and store it inside a String variable.
My problem is that the "reading action" is a "Future" function and I have some troubles to save its value in a "String".
I read the file with :
Future<String> get _localPath async {
final directory = await getApplicationDocumentsDirectory();
return directory.path;
}
Future<File> _localFile(String name) async {
final path = await _localPath;
return File('$path/$name');
}
Future<String> _read(String filename) async {
try {
final file = await _localFile(filename);
// Read the file.
return await file.readAsString();
} catch (e) {
// If encountering an error, return 0.
return "Can't read";
}
}
And I would like to save it with :
String _bio = _read("bio.txt").then((value) => String);
Do you know why this solution isn't working?
Any suggestion?
Because the then of Futures won't return a value, it should be like this,
var _bio;
_read("bio.txt").then((value) {
_bio = value;
});
or by making the context _bio is in to an asynchronous one,
var _bio = await _read("bio.txt");
You can either use a then block or use the async/await
_read ('file.txt').then((value){
bio = value;
});
Or:
bio = await _read ('file.txt');
This is my solution :
String _myRead( String filename){
var _bio;
_read("bio.txt").then((String) {
_bio = String;
});
return _bio;
}
String _bio=_myRead("bio.txt");

Firebase startAfter is not working for doc ref

Docs I am following: https://firebase.google.com/docs/firestore/query-data/query-cursors
I have code like below;
async List(query: any): Promise<Array<any>> {
let collectionQuery = super.GetCollectionReference();
if (query.VideoChannelId) {
collectionQuery = collectionQuery.where(
"VideoChannel.Id",
"==",
query.VideoChannelId
);
}
let startAfterDoc: any = "";
if (query.StartAfter) {
startAfterDoc = await super.GetDocumentReference(query.StartAfter);
}
collectionQuery = collectionQuery
.orderBy(query.OrderBy, "desc")
.startAfter(startAfterDoc)
.limit(query.Limit);
let items = await super.List(collectionQuery);
return items;
}
And utility methods:
GetDocumentReference(id: string): any {
return this.GetCollectionReference().doc(id);
}
async GetDocumentSnapshot(id: string): Promise<any> {
return await this.GetDocumentReference(id).get();
}
GetCollectionReference(): any {
return this.db.collection(this.CollectionName);
}
Regardless what ever value I pass for query.StartAfter it always returns top document in the collection.
I am pretty sure document exists with id query.StartAfter.
If I use GetDocumentSnapshot instead of GetCollectionReference, then I am getting parse error at firebase API.
Indexes has been added for query.OrderBy (CreateDate) and Id fields.
What possibly I would be missing here?

Making an asynchronous function synchronous for the Node.js REPL

I have a library that connects to a remote API:
class Client(access_token) {
void put(key, value, callback);
void get(key, callback);
}
I want to set up a Node.js REPL to make it easy to try things out:
var repl = require('repl');
var r = repl.start('> ');
r.context.client = new Client(...);
The problem is that an asynchronous API is not convenient for a REPL. I'd prefer a synchronous one that yields the result via the return value and signals an error with an exception. Something like:
class ReplClient(access_token) {
void put(key, value); // throws NetworkError
string get(key); // throws NetworkError
}
Is there a way to implement ReplClient using Client? I'd prefer to avoid any dependencies other than the standard Node.js packages.
You can synchronously wait for stuff with the magic of wait-for-stuff.
Based on your example specification:
const wait = require('wait-for-stuff')
class ReplClient {
constructor(access_token) {
this.client = new Client(access_token)
}
put(key, value) {
return checkErr(wait.for.promise(this.client.put(key, value)))
}
get(key) {
return checkErr(wait.for.promise(this.client.get(key)))
}
}
const checkErr = (maybeErr) => {
if (maybeErr instanceof Error) {
throw maybeErr
} else {
return maybeErr
}
}

Await keyword can't be used in the following code. I couldn't find out why

Why can't I use await in this below block?
VS throws compile error if I use await keyword in the following code.
[ResponseType(typeof (ApiTableDetailDto))]
public async Task<IHttpActionResult> GetApiTable(int id)
{
var apiTable = await Mapper.Map<ApiTableDetailDto>(_unitOfWork.ApiTableRepository.GetById(id));
if (apiTable == null)
{
return NotFound();
}
return Ok(apiTable);
}
Please do advise.
Well the question has actually been answered by #shf301, but I thought I'd throw in an example on how you can await in this case.
If the _unitOfWork have Async methods then you can do it like this:
var response = await _unitOfWork.ApiTableRepository.GetByIdAsync(id);
var apiTable = Mapper.Map<ApiTableDetailDto>(response);

Resources