I am exporting JSON by fetch from the URL. I think I have a binding issue if take from local data file working I'm not completely sure on how I should proceed to bind my function.
Data.js
const Json = require('./one.js'); // not working or const Json = require('./two.json'); // working
export default Json;
one.js
function getvals(){
return fetch('http://xxxxxx')
.then((response) => response.json())
.then((json) => {
return json.products;
})
.catch((error) => {
console.error(error);
});
}
getvals().then(response => response);
two.json
[{"id":"1","category":"kkk","title":"sss"}]
Nothing in one.js exports anything. With CommonJS-style modules, you export something by assigning it to a property on exports (or by reassigning the exports variable entirely).
But note that since what you're getting is only available asynchronously, other modules may request one.js's default export before the asynchronous process has completed. The usual solution to that is export the promise from fetch:
module.exports = fetch('http://xxxxxx')
.then((response) => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
})
.then((data) => {
return data.products;
});
Also note that you need to check for HTTP success (the footgun in the fetch API) and you don't want to hide errors; let the users of the module know if the fetch fails.
Code using that would need to use the promise, e.g.:
require("./one.js")
.then(data => {
// ...use the products...
})
.catch(error => {
// ...handle the fact the fetch failed and the data won't be coming...
});
I don't know the React Native ecosystem, but if you can to switch to JavaScript modules ("ESM" = ECMAScript Modules) instead (and if you want to), someday you'd be able to use a new feature called top-level await. The V8 engine has it (behind a flag), presumably JavaScriptCore will at some stage. That would let you suspend module evaluation until the fetch completed, and directly export the result:
// With top-level `await` in an ESM module
export default await fetch('http://xxxxxx')
.then((response) => {
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
})
.then((data) => {
return data.products;
});
Modules using it would be able to get the products directly:
import products from "./one.js";
If you're using Webpack (again, I don't know the React Native ecosystem), it has experimental support for it, too.
Related
I'm in need of your expertise in React Native.
I'm trying to use expo-local-authentication for local fingerprint authentication for my application.
My project was created using expo init command.
I have done the setup as per the documentation and still running into a strange issue:
Below is the error I'm facing for LocalAuthentication.authenticateAsync(options):
Native method ExpoLocalAuthentication.authenticateAsync expects 0
arguments but received 1
Here is the required part of my code:
import * as LocalAuthentication from 'expo-local-authentication';
const authenticate = async () => {
const hasHardwareAsync = await LocalAuthentication.hasHardwareAsync();
if (hasHardwareAsync) {
const supportedAuthentications = await LocalAuthentication.supportedAuthenticationTypesAsync();
if (supportedAuthentications.indexOf(1) !== -1) {
// Finger print supported
const isFingerprintEnrolled = await LocalAuthentication.isEnrolledAsync();
if (isFingerprintEnrolled) {
const options = {
promptMessage: 'Authenticate yourself',
};
try {
// Also tried with await but it throws the same error
// await LocalAuthentication.authenticateAsync(options)
LocalAuthentication.authenticateAsync(options).then(result => {
// I never get inside this block
console.warn(result)
})
.catch(error => {
console.warn('Authentication Error: ', error)
})
} catch (error) {
console.warn(error)
}
}
}
}
}
Not sure what I'm missing. Seems like there is no information available about the error. I also tried to run the LocalAuthentication.authenticateAsync() without any arguments but it still throws the same error.
Any help on what could be the root cause of the issue and how can I resolve it or any other alternative for local authentication would be highly appreciated.
Update your app to the latest version of expo (38 in my case) and to the latest version of expo-local-authentication, and the error goes away.
I am building an Android app using Ionic. And using the following feathers_client.js
const feathers = require('#feathersjs/feathers');
const socketio = require('#feathersjs/socketio-client');
const auth = require('#feathersjs/authentication-client');
const io = require('socket.io-client');
const socket = io('http://mydomain.example:3030');
const feathers_client = feathers();
feathers_client
.configure(socketio(socket))
.configure(auth({ storage: window.localStorage }));
module.exports = feathers_client;
When I run the app at the browser it works fine. But when I run it at an Android device I only get "NotAuthenticated".
I am assuming this is happening because FeathersJS stores the JWT token at window.localStorage and this is not available at the Android app userspace.
Two questions:
1) Is there any way to tell FeathersJS to store this token somewhere else?
2) If not, anyone faced this situation and may provide me a solution?
By the way, this is my code for authenticating:
export class SSHSettingsPage implements OnInit {
public inputEmail: string;
public inputPassword: string;
constructor() { }
ngOnInit() {
}
public performLogin($event) {
let authObj: object = { "strategy": "local", "email": this.inputEmail, "password": this.inputPassword};
client.authenticate(authObj)
.then(res => {
console.log(res);
window.localStorage.setItem("user",JSON.stringify(res.user));
window.location.href = "/download";
})
.catch(err => {
console.log(err);
window.location.href = "/login-error";
})
}
}
As mentioned in the configuration API the storage option can be passed an instance of the React Native AsyncStorage:
import {AsyncStorage} from 'react-native';
// Available options are listed in the "Options" section
app.configure(auth({
storage: AsyncStorage
}))
I'm having an ugly issue that only affect my expo app on Android.
Im trying to upload a base64 image taken with expo ImagePicker to Firebase Storage passing the image value with a http-request made with axios to a Firebase Cloud Function which returns the url of the saved image. This url goes in Firestore, but this is out of reach of my question I think.
My current implementation works flawless in IOS (I can get as many urls as I want, they upload pretty quick actually) but, in Android I only can upload 2 images in a row; when I try for the third time, my app get frozen when reach axios/fetch* statement and gives no clue of whats happened. Console is just as it was before trying the third time and the apps or simulators freeze.
Here you can see this behaviour in a 2 min video:
https://youtu.be/w66iXnKDmdo
When I begun working in this bug I was using fetch instead of axios. At that time the issue was that I was able to upload only one image. It were necessary to close and open the app again to upload one more. Now with axios Im able to upload 2 insted of one, but the problem persist.
This is how I implemented the code:
const imageBase64 = 'QWEpqw0293k01...'
This is how I upload the image to Firebase Cloud Storage:
export const savePhoto = (imageBase64) => {
const db = firebase.firestore();
const docRef = db.collection('Comidas').doc();
return () => {
uploadImageToFirestore(imageBase64)
.then(imageUrl => {
console.log('image-url: ', imageUrl);
docRef.set({ imagen: { uri: imageUrl }, });
})
.catch(err => console.log('error: ', err));
};
};
I made a function helper that allow me to make the http request reusable:
import axios from 'axios';
export const uploadImageToFirestore = (imageBase64) => {
//<--- here is where it get frozen the third time
//<--- console.log() calls three times but not axios
return axios({
method: 'post',
url: 'https://us-central1-menuapp-9feb4.cloudfunctions.net/almacenamientoImagen',
data: {
image: base64
},
})
.then(res => res.data.imageUrl)
.catch(err => console.log('error while uploading base64: ', err));
};
This invoques the following Firebase Cloud Function:
exports = module.exports = functions.https.onRequest((req, res) => {
cors(req, res, () => {
const body = req.body;
console.log('image: ', body.image);
fs.writeFileSync("/tmp/uploaded-image.jpg", body.image, "base64", err => {
console.log(err);
return res.status(500).json({ error: err });
});
const bucket = gcs.bucket("myapp.appspot.com");
const uuid = UUID();
bucket.upload(
"/tmp/uploaded-image.jpg",
{
uploadType: "media",
destination: "/comidas/" + uuid + ".jpg",
metadata: {
metadata: {
contentType: "image/jpeg",
firebaseStorageDownloadTokens: uuid
}
}
},
(err, file) => {
if (!err) {
console.log('url: ', {
imageUrl:
"https://firebasestorage.googleapis.com/v0/b/" +
bucket.name +
"/o/" +
encodeURIComponent(file.name) +
"?alt=media&token=" +
uuid
});
res.status(201).json({
imageUrl:
"https://firebasestorage.googleapis.com/v0/b/" +
bucket.name +
"/o/" +
encodeURIComponent(file.name) +
"?alt=media&token=" +
uuid
});
} else {
console.log(err);
res.status(500).json({ error: err });
}
}
);
});
});
I know that axios it’s not being called because there is no log neither register of the Firebase Cloud Function execution.
I expect this code to upload as many images as user consider he/she needs, not just 2 per app session as it does at this moment
How can I solve this?
I'm using the following plugin https://github.com/EddyVerbruggen/nativescript-plugin-firebase allowing to access Firebase from Nativescript applicaiton.
For some reasons, when I do a query request to get my objects, some properties of the json objects are missed.
Below the query :
return firebase.query(
data => {
if(data.value) {
Object.keys(data.value).forEach(key => {
this.results.push(data.value[key]); // Here I dont get exactly the JSON, some properties disapears.....
}
}
}, "/ads/",
{ orderBy: { type: firebase.QueryOrderByType.KEY }})
.then(result => { return result; })
);
My database
Properties of type number are not loaded (totalProduct and state).
Regards
I find out that your forEach miss a ')'.
After modified, everything is fine. All of the JSON properties still exist.
I'm currently working on a Ionic/Cordova application, a to-do application. I am using the ngCordova library for an easier use of the cordova plugins. I'm also using the Sqlite plugin by litehelpers (GitHub page).
My problem is about the correct understanding of the JavaScript's promises behavior. I have a Angular service called "Projects", which make use of the SQLite plugin, and a "Tasks" controller which is delegated to it.
angular.module('myapp.services', [])
.factory("Projects", ["$ionicPlatform", "$cordovaSQLite", "$window", "$q",
function($ionicPlatform, $cordovaSQLite, $window, $q) {
return {
// SOME FUNCTIONS..
getCurrentProject: function() {
var q = $q.defer();
$ionicPlatform.ready(function() {
$cordovaSQLite.execute(db,
"SELECT id_project, name FROM projects WHERE active = 1").then(
function(res) {
q.resolve(res.rows.item(0));
}, function(err) {
q.reject(err);
console.error(err.message);
});
});
return q.promise;
}
};
}
]);
I want to make this function return an object, which is the result of my query.
The promises and callback keywords are confusing me.
I've tried a few ways to solve my problem, but when I call (in my controller):
var currentProject = Projects.getCurrentProject();
And then trying to check its values with:
console.log("ID -> " + currentProject.id_project);
console.log("NAME -> " + currentProject.name);
I always get undefined. How do I handle a promise in a Ionic/Cordova Application?
Solved
#bardzusny's answer totally made me realize where i was wrong, thank you all :)
Promises are designed to be chainable with error handling and final behavior (optional), like so:
Projects.getCurrentProject()
.then (project) -> currentProject = project
.catch (err) -> console.error err
.finally () -> wrapUpFn()
So you would need to use .then to make the assignment. Otherwise you're assigning currentProject to the promise object, not the result of the promise object (which is what you want).
EDIT
Now in javascript :)
var currentProject
Projects.getCurrentProject()
.then(function(project) {
currentProject = project
})
.catch(function(err) {
console.error(err)
})
.finally(function() {
wrapUpFn()
})
As an aside, promise objects are great because you can just keep on chaining down the line with .thens, and still keep your error handling and final behaviors clear. This lets you create simple flows that are ordered within the crazy world of javascript.