Function constructor method - javascript

How can i use this method from my own project/design
Github.prototype.handleErr = function(res) {
if(!res.ok) {
throw new Error('Something went wrong!!' + res.status);
}
return res;
}
Inside another method but the same object
const git = new Github();
Github.prototype.getUser = (user) => {
return new Promise((resolve, reject) => {
// Profile
fetch(something)
.then(this.handleErr)
.then(response => response.json())
.then(data => resolve(data))
.catch(err => reject(err));
})
}
it didn't work with this.handleErr
i wanted to make a fetch request and use the git.handleErr() function inside .then() consumer, before handling the data response.

Ok so i figured out. I modified the arrow function syntax
Github.prototype.getUser = (user) => {}
to the normal syntax
Github.prototype.getUser = function(user) {}
Acording to this it was referred as a global/undefined this. so that's why it didn't work in the first instance. Thank you str.

Related

Call backup endpoint in case get promise fails

I have a method returning a promise that either resolves or rejects.
myMethod() {
return new Promise((resolve, reject) => {
axiosClient
.get(endpoint)
.then((response) => {
resolve(response.data);
})
.catch((error) => {
reject(error);
});
});
}
Is there a way to return another promise in case this produces an error, calling a backup endpoint?? Something along the lines of:
myMethod() {
return new Promise((resolve, reject) => {
axiosClient
.get(endpoint)
.then((response) => {
resolve(response.data);
})
.catch(() => {
axiosClient
.get(backupEndpoint)
.then((response) => {
resolve(response.data);
})
.catch((error) => {
reject(error);
});
});
});
Edit: if this is a duplicate I have not been able to find something about it that is specific to this point. Could it be because it's a bad practice?
Edit2: thanks for the answers, maybe I should clarify better the flow I want to achieve:
get endpoint -> (if this fails) get fallback endpoint -> (if this fails aswell) reject the entire promise
From the above, one could simplify it doing with re-usability best practices,
as follows:
myMethod() {
const PromiseHandler = url => {
/**
* this function recevies url
* makes the request and return
* a reposne form the end point
*/
return axiosclient.get(url).then(res => res.data)
}
return PromiseHandler(endpoint)
.catch(() => {
return PromiseHandler(backupEndPoint)
}

chaining promises in functions

I have a small problem, how to create a promise chain in a sensible way so that the makeZip function will first add all the necessary files, then create the zip, and finally delete the previously added files? (The makeZip function also has to return a promise). In the example below I don't call deleteFile anywhere because I don't know exactly where to call it. when I tried to call it inside the add file function to delete the file immediately after adding it, for some unknown reason the console displayed the zip maked! log first and then file deleted.
const deleteFile = (file, result) => {
new Promise((resolve, reject) => {
fs.unlink(`./screenshots/${file}`, (err) => {
if (err) return reject(err);
console.log(`${file} deleted!`);
return resolve();
});
});
};
const addFile = (file) => {
new Promise((resolve, reject) => {
try {
zip.addLocalFile(`./screenshots/${file}`);
console.log(`${file} added`);
return resolve();
} catch {
return reject(new Error("failed to add file"));
}
});
};
const makeZip = () => {
Promise.all(fs.readdirSync("./screenshots").map((file) => addFile(file)))
.then(() => {
return new Promise((resolve, reject) => {
try {
zip.writeZip(`./zip_files/supername.zip`);
console.log("zip maked!");
resolve();
} catch {
return reject(new Error("failed making zip"));
}
});
})
.catch((err) => console.log(err));
};
the main cause of this is that you are not returning the promises you are instantiating in your function calls. Also I have some cool suggestion to make that can improve you code cleanliness.
[TIP]: Ever checked the promisify function in NodeJS util package, it comes with node and it is very convenient for converting functions that require callbacks as arguments into promise returning functions., I will demonstrate below anyhow.
// so I will work with one function because the problem resonates with the rest, so
// let us look at the add file function.
// so let us get the promisify function first
const promisify = require('util').promisify;
const addFile = (file) => {
// if addLocalFile is async then you can just return it
return zip.addLocalFile(`./screenshots/${file}`);
};
// okay so here is the promisify example, realized it wasn't applicable int the function
// above
const deleteFile = (file, result) => {
// so we will return here a. So because the function fs.unlink, takes a second arg that
// is a callback we can use promisify to convert the function into a promise
// returning function.
return promisify(fs.unlink)(`./screenshots/${file}`);
// so from there you can do your error handling.
};
So now let us put it all together in your last function, that is, makeZip
const makeZip = () => {
// good call on this, very interesting.
Promise.all(fs.readdirSync("./screenshots").map((file) => addFile(file)))
.then(() => {
return zip.writeZip(`./zip_files/supername.zip`);
})
.then(() => {
//... in here you can then unlink your files.
});
.catch((err) => console.log(err));
};
Everything should be good with these suggestions, hope it works out...
Thank you all for the hints, the solution turned out to be much simpler, just use the fs.unlinkSync method instead of the asynchronous fs.unlink.
const deleteFile = (file) => {
try {
fs.unlinkSync(`./screenshots/${file}`);
console.log(`${file} removed`);
} catch (err) {
console.error(err);
}
};
const addFile = (file) => {
try {
zip.addLocalFile(`./screenshots/${file}`);
console.log(`${file} added`);
deleteFile(file);
} catch (err) {
console.error(err);
}
};
const makeZip = () => {
fs.readdirSync("./screenshots").map((file) => addFile(file));
zip.writeZip(`./zip_files/supername.zip`);
console.log("zip maked!");
};

Catch error in promise from a service in an Angular component

Hi everyone running into a problem with a post service I created in angular. Struggling to catch the error from my component when I call the service. I was able to catch the error from the service but I need to do this from my component to properly handle the error. Any advice would be greatly appreciated.
Service
sendData(obj) {
let promise = new Promise((resolve) => {
this.http.post(this.URL, obj, this.httpOptions)
.toPromise()
.then(
res => {
console.log(res);
resolve(res);
}
)
//.catch((err) => {
// console.log(err);
// throw err;
//});
});
return promise;
}
Component
this._myservice.sendData(this.myobj)
.then(function (res) {
console.log('data sent');
})
.catch(error => {
console.warn('from component:', error);
// this console warn never gets logged out
});
Do I need to update something in my service to allow me to catch the error from the component?
You're creating your own Promise here, but you never call reject if the Promise you're wrapping rejects (throws an error). This is known as the the new Promise antipattern. In your case, you can simply remove this wrapper and replace the call to resolve with a return in order to achieve what you need, like so:
sendData(obj) {
return this.http.post(this.URL, obj, this.httpOptions)
.toPromise()
.then(res => {
console.log(res);
return res;
});
}
In order to provide more context, you could fix your original problem by calling reject. This would look like this:
// DONT'T DO THIS
sendData(obj) {
let promise = new Promise((resolve, reject) => {
this.http.post(this.URL, obj, this.httpOptions)
.toPromise()
.then(res => {
console.log(res);
resolve(res);
})
.catch((err) => {
console.log(err);
reject(err); // Here.
});
});
return promise;
}
But, as I said above, this is overcomplicated and unnecessary. I hope that it demonstrates how the Promise your component has access to could never see errors that occurred in the HTTP call.

How to handle an array of Promises then/catch

I don't know to to resolve this situation using JS promises.
Imagine I have some articles and I want to send a patch request to update them. I send one request per article. If the request of one article success then I update that article, but if the request fails, then I update the article differently. Also I want to show a message to the user informing if all the articles have been updated correctly or not.
This is not my real scenario and this may be a weird example. But it's what I want to accomplish in my React app.
Here is what I'm trying to do right now:
const saveArticles = articles => {
const promises = [];
articles.forEach(article => {
const promise = axios
.patch('/articles', article)
.then(() => updateArticleUi(article))
.catch(() => updateArticleUiWithError(article));
promises.push(promise);
});
Promise.all(promises)
.then(() => tellTheUserThereWasNoErrors())
.catch(() => tellTheUserThereWasSomeErrors());
};
This isn't working because the Promise.all is always executing the then callback, weather all promises succeed or not.
Thanks!
Your updateArticleUi and updateArticleUiWithErrors should have the respective return values so that you can distinguish whether there was an error or not when looking at the array of results:
function updateArticleUi(article) {
…
return {success: true};
}
function updateArticleUiWithError(article, error) {
…
return {success: false};
}
function saveArticles(articles) {
const promises = articles.map(article => {
return axios.patch('/articles', article).then(() =>
updateArticleUi(article)
, err =>
updateArticleUiWithError(article, err)
);
});
return Promise.all(promises).then(results =>
if (results.every(res => res.success)) {
tellTheUserThereWasNoErrors();
} else {
tellTheUserThereWasSomeErrors();
}
});
}
This works:
function axiosPatchRequest(url,data) {
return new Promise(function (resolve, reject) {
if (data) {
resolve(url);
} else {
reject('DATA_NOT_FOUND');
}
})
}
function updateArticleUi(data,article) {
return new Promise(function (resolve, reject) {
resolve({type:"updateArticleUi ",data,article});
})
}
function updateArticleUiWithError(data,article) {
return new Promise(function (resolve, reject) {
reject({type:"updateArticleUiWithError ",data,article});
})
}
function tellTheUserThereWasNoErrors(data){
console.log("tellTheUserThereWasNoErrors",data);
}
function tellTheUserThereWasSomeErrors(error){
console.log("tellTheUserThereWasSomeErrors",error);
}
const execute = (articles)=>{
const promises = [];
articles.forEach(article => {
const promise = axiosPatchRequest('/articles', article)
.then((data) => {
return updateArticleUi(data,article);
})
.catch((error) => {
return updateArticleUiWithError(error,article);
});
promises.push(promise);
});
Promise.all(promises)
.then((data) => tellTheUserThereWasNoErrors(data))
.catch((error) => tellTheUserThereWasSomeErrors(error));
};
execute(["one","","three"]);
execute(["one","two","three"]);
Promise.all will always call then because the promise you add to promises is already resolved one with either then or catch attached above
if you want to see catch to happen in .all chain just throw some exeption in updateArticleUiWithErro function
The problem is that you are catching the error thrown by
const promise = axios
.patch('/articles', article)
.then(() => updateArticleUi(article))
.catch(() => updateArticleUiWithError(article));
you should either throw a new error in the axios catch() or let the error bubble up by removing the catch from the axios call.

Why can't I store the result of a promise (or a chained promise) in a variable?

This is a silly question but can you explain what is wrong with this code?
Why can't I perform this?
const fetch = require('node-fetch');
const fetchProm = (() => {
return fetch('https://api.github.com/users/github');
}).then((response) => {
return response.json();
}).then((json) => {
console.log(json)
});
Declaring a function is not the same as calling one
You are not calling the function that returns the promise, just declaring it. You'll need to add an additional set of parentheses before the first .then() in order to actually call the function:
const fetch = require('node-fetch');
const fetchProm = (() => {
return fetch('https://api.github.com/users/github');
})().then((response) => {
return response.json();
}).then((json) => {
console.log(json)
});
If you want to call everything at a later time, you need to place the whole thing in its own function where the promises get handled in an isolated scope:
const fetch = require('node-fetch');
const fetchProm = () => {
fetch('https://api.github.com/users/github')
.then(response => response.json())
.then(json => console.log(json));
};
fetchProm();

Categories

Resources