How to pass a reference to a Boolean in es6 or better solution for Vue - vue.js

I am picking up a Vue project and would like to pass a reference to a "spinner" for fetch requests. If an error, I'd like to pass a reference in the checkIfError method below rather than just the Boolean value. Something like this:
checkIfError(response, loadingStatus){
if (!response.ok) {
loadingStatus = false; // I'd like to set this.loadingQuotes to false and not set true to false
const message = `An error has occured: ${response.status}`;
msg = "this is jacked up";
alert(message);
throw new Error(message);
}
},
getQuotes(){
this.loadingQuotes = true;
const response = await fetch("/quotes");
this.checkIfError(response, this.loadingQuotes);
}
But this obviously doesn't work. How could I pass a reference this way?
I was thinking of passing an object literal like this.checkIfError(response, {targetStatus: this.loadingQuotes}) but suspect this just passes {status: true}.

Related

Sending response in async function

I need to return an array of labels, but I can only return 1 of the labels so far. The error which I get is "Cannot set headers after they are sent to the client". So I tried res.write and placed res.end after my for loop then I get the obvious error of doing a res.end before a res.write. How do I solve this?
for(let i=0;i<arr.length;i++){
request.get(arr[i], function (error, response, body) {
if (!error && response.statusCode == 200) {
myfunction();
async function myfunction(){
const Labels = await Somefunctioncallwhoseresponseigetlater(body)
res.send(Labels);
}
}
});}
New code-
async function getDataSendResponse(res) {
let allLabels = [];
for (let url of arr) {
let body = await got(url).buffer();
var imgbuff= Buffer.from(body,'base64')
const imageLabels = await rekognition.detectLabels(imgbuff);
allLabels.push(...imageLabels);
}
res.send(allLabels);
}
The error I have with this code is
"Resolver: AsyncResolver
TypeError: Cannot destructure property Resolver of 'undefined' or 'null'."
You are trying to call res.send() inside a for loop. That means you'll be trying to call it more than once. You can't do that. You get to send one response for any given http request and res.send() sends an entire response. So, when you try to call it again inside the loop, you can the warning you see.
If what you're trying to do is to send an array of labels, then you need to accumulate the array of labels first and then make one call to res.send() to send the final array.
You don't show the whole calling context here, but making the following assumptions:
Somefunctioncallwhoseresponseigetlater() returns a promise that resolves when it is done
You want to accumulate all the labels you collected in your loop
Your Labels variable is an array
Your http request returns a text response. If it returns something else like JSON, then .text() would need to be changed to .json().
then you can do it like this:
const got = require('got');
async function getDataSendResponse(res) {
let allLabels = [];
for (let url of arr) {
let body = await got(url).buffer();
const labels = await Somefunctioncallwhoseresponseigetlater(body);
allLabels.push(...labels);
}
res.send(allLabels);
}
Note, I'm using the got() library instead of the deprecated request() library both because request() is not deprecated and because this type of code is way easier when you have an http library that supports promises (like got() does).

How to access 'this' tag instance inside tag lifecycle event?

I'm trying to update an array every time my tag receives an update from parent tags. Here is my code:
var tag = function(opts){
this.set = [];
var self = this;
this.on('updated', function(){
var obj = opts.my_topics;
var better_obj = {};
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var topic_title = key;
better_obj = obj[key];
better_obj['title'] = key;
}
}
self.set.push(better_obj);
})
}
Whenever I try to push(), I get an error: Uncaught SyntaxError: Unexpected token ; database.js:60. The moment I remove the line of code for the push, the error disappears. Am I using this/self wrong in this case or could it be something else?
What I am trying to accomplish here is taking an object from opts (which receives regular updates), converting into an array, and using it for an each loop within my tag. I do not know how to do this other than a) what i'm trying to do now by accessing this, or b) rewiring my opts to deliver an array rather than an object (which is currently failing for me as I'm using Redux and it doesn't like dispatching non-objects).

vue.js - Cannot read property 'toLowerCase' of undefined

I am filtering projects with a computed property like this:
filtered_projects() {
return this.projects.filter( (project) => {
return project.title.toLowerCase().indexOf(this.project_filter.toLowerCase()) !== -1
})
}
When I add a new project using this
submitNewProject() {
let path = '/api/projects';
Vue.http.post(path, this.project)
.then( (rsp) => {
this.projects.push(rsp.data);
this.project = this.getSingleProject();
this.create_project = false;
return true;
});
}
This is giving me an error that I can't find
TypeError: Cannot read property 'toLowerCase' of undefined
It may just be that you are not correctly passing the projects data to the projects array.
Firstly vue-resource now uses body not data to get the response, therefore you may need to use:
this.projects.push(rsp.body)
then this will give you a single array item containing all projects which doesn't look like what you want. I believe instead you're after:
this.projects = rsp.body
Assuming the response body is an array of objects this will then allow:
this.projects.filter(project => {})
to work as expected. Meaning project.title should now be valid
EDIT
For a project title to be set to lowerCase you must be returning an object with a title param, i.e.
rsp.body = {
title: 'FOO',
}
which you'd then set on the projects array via:
this.projects.push(rsp.body)
so the first thing to fix is your response, sort your endpoint so it returns what you are expecting, then the rest of the above code should work
You need preserve "this" before Vue.http.post (self=this) and then in callback change this.projects to self.projects.
Explanation:
How to access the correct `this` context inside a callback?

Prevent duplicate routes in express.js

Is there a nice way to prevent duplicate routes from being registered in express? I have a pretty large application with hundreds of routes across different files, and it gets difficult to know if I've already registered a certain route when I go to add a new one. For example, I'd like to throw an error when express gets to routes487.js:
File: routes1.js
var ctrl = require('../controllers/testctrl');
var auth = require('../libs/authentication');
module.exports = function (app) {
app.get('/hi', auth.getToken, ctrl.hi);
app.get('/there', auth.getToken, ctrl.there);
};
File: routes487.js
var ctrl = require('../controllers/testctrl487');
var auth = require('../libs/authentication');
module.exports = function (app) {
app.get('/hi', auth.getToken, ctrl.hi487);
};
You could try a custom solution by wrapping express methods with the validation. Consider the following modification to your express app:
// route-validation.js
module.exports = function (app) {
var existingRoutes = {}
, originalMethods = [];
// Returns true if the route is already registered.
function routeExists(verb, path) {
return existingRoutes[verb] &&
existingRoutes[verb].indexOf(path) > -1;
}
function registerRoute(verb, path) {
if (!existingRoutes[verb]) existingRoutes[verb] = [];
existingRoutes[verb].push(path);
}
// Return a new app method that will check repeated routes.
function validatedMethod(verb) {
return function() {
// If the route exists, app.VERB will throw.
if (routeExists(verb, arguments[0]) {
throw new Error("Can't register duplicate handler for path", arguments[0]);
}
// Otherwise, the route is saved and the original express method is called.
registerRoute(verb, arguments[0]);
originalMethods[verb].apply(app, arguments);
}
}
['get', 'post', 'put', 'delete', 'all'].forEach(function (verb) {
// Save original methods for internal use.
originalMethods[verb] = app[verb];
// Replace by our own route-validator methods.
app[verb] = validatedMethod(verb);
});
};
You just need to pass your app to this function after creation and duplicate route checking will be implemented. Note that you might need other "verbs" (OPTIONS, HEAD).
If you don't want to mess with express' methods (we don't know whether or how express itself or middleware modules will use them), you can use an intermediate layer (i.e., you actually wrap your app object instead of modifying its methods). I actually feel that would be a better solution, but I feel lazy to type it right now :)

angularFire not binding to objects

I'm trying to write to an object in firebase, here is how i did it:
var myDataRef = new Firebase('https://ootest1.firebaseio.com/users/' + '-J6kDooooooz_eV3Cq' /*JobsManager.getCurrentUser().username*/);
angularFire(myDataRef, $scope, 'newUser');
if (!$scope.newUser.jobs)
$scope.newUser.jobs = [];
The problem is that $scope.newUser is undefined.
Why is that?
The angularFire binding returns a promise, and the $scope.newUser model won't be defined until that promise is fulfilled:
var promise = angularFire(myDataRef, $scope, 'newUser');
// $scope.newUser is undefined
promise.then(function(){
// $scope.newUser is defined
}