I need to pull inventory data to my NextJS app, I am then trying to store that data to localStorage, but it never gets set. What am I doing wrong?
if (process.browser && localStorage.getItem('inv') === undefined) {
const inv = await getInventory()
localStorage.setItem('inv', inv)
}
getInventory() is just a node script that pulls inventory data from a remote api and returns fullInventory.
Here is the code from getInventory():
const getInventory = async () => {
const token = await refreshToken()
const header = {
Authorization: `Bearer ${token}`,
};
const queries = await getQueriesCount();
axios.interceptors.response.use(function (response) {
return response;
}, async function (error) {
await new Promise(function (res) {
setTimeout(function () { res() }, 2000);
});
const originalRequest = error.config;
if (error.response.status === 401 && !originalRequest._retry) {
originalRequest._retry = true;
const refreshedHeader = await setHeader()
axios.defaults.headers = refreshedHeader
originalRequest.headers = refreshedHeader
return Promise.resolve(axios(originalRequest));
}
return Promise.reject(error);
});
let fullInventory = [];
for (let i = 0; i < queries; i++) {
setTimeout(async () => {
try {
const res = await axios({
url: `${MyApi}/Item.json&offset=${i * 100}&customSku=!~,`,
method: "get",
headers: header,
});
console.log(`adding items ${i * 100} through ${(i + 1) * 100}`);
const items = await res.data.Item;
items[0]
? (fullInventory = fullInventory.concat(items))
: fullInventory.push(items);
if (i + 1 === queries) {
return fullInventory;
}
} catch (error) {
console.error("We have a problem here: ", error.response);
}
}, 2000 * i);
};
}
Related
I'm trying to store and get data that I fetch from an API. The user is supposed to get a token on the login screen, and the token will be shown in an Alert dialog on home screen when the user press a button. But the token is not shown in the Alert dialog. the token is shown after I reload(not refresh the app. I used Live Server extension) the screen three times.
Login.js
const _userLogin = () => {
fetch(URLs._login, {
method: "POST",
headers, body,
})
}).then((response) => response.json())
.then((result) => {
if(result.message !== "Unauthorized / Access Token Expired" && result.message !== "The given data was invalid."){
storeData(result.access_token, result.token_type);
navigation.navigate('HomeScreen');
} else {
Alert.alert("Error", result.message);
}
});
};
const storeData = async (accessToken, tokenType) => {
try {
await AsyncStorage.setItem('#access_token', accessToken);
await AsyncStorage.setItem('#token_type', tokenType);
await AsyncStorage.setItem('#user_auth', tokenType + " " + accessToken);
} catch (e) {
console.log(e);
}
}
Home.js [UPDATE]
const [inputs, setInputs] = React.useState({
userToken: '',
userPointsBalance: '',
expiringOn: '',
});
useEffect (() => {
_dashboard();
})
const getToken = async () => {
inputs.userToken = await AsyncStorage.getItem('#user_auth');
}
const _dashboard = () => {
getToken();
fetch(URLs._dashboard, {
method: "GET",
headers: {
'Authorization': inputs.userToken,
'Content-Type': 'application/json',
},
}).then((response) => response.json())
.then(async (result) => {
storeData(result.code, result.name, result.member_name, result.user_points_balance, result.expiring_on, result.status, result.token_id);
getData();
});
};
const storeData = async (code, name, memberName, userPointsBalance, expiringOn, status, tokenId) => {
try {
await AsyncStorage.setItem('#user_points_balance', userPointsBalance.toString());
await AsyncStorage.setItem('#expiring_on', expiringOn.toString());
} catch (e) {
console.log(e);
}
}
const getData = async () => {
const userPointsBalance = await AsyncStorage.getItem('#user_points_balance');
const expiringOn = await AsyncStorage.getItem('#expiring_on');
setInputs({userPointsBalance: userPointsBalance, expiringOn: expiringOn});
}
return (
<Text>{inputs.expiringOn}<Text>
)
i hope it works
.then(async(result) => {
if(result.message !== "Unauthorized / Access Token Expired" && result.message !== "The given data was invalid."){
await storeData(result.access_token, result.token_type)
.then(res=>
navigation.navigate('HomeScreen')
)
} else {
Alert.alert("Error", result.message);
}
});
here I have pasted code which is written class component for mobx state management and i am calling it to another file,the thing is I have above 450 api responses and it need to store locally so i have tried it but i am not getting any value nor the data stored in database pls help me out thanks in advance ..
class ProductStore {
constructor() {
makeAutoObservable(this);
}
screenWidth = width;
screenHeight = height;
headerHeight = 0;
isiOS = Platform.OS === 'ios';
isAndroid = Platform.OS === 'android';
isProductLoading = 'pending';
productData = [];
filterdData = [];
search = '';
isFlatlistRender = false;
setFields(eName, data) {
this[eName] = data;
console.log(eName, data);
}
getproductData = () => {
if (this.isProductLoading == 'loading') {
return true;
}
this.isProductLoading = 'loading';
this.productData = [];
let headers = new Headers();
headers.set(
'Authorization',
'Basic ' + encode('username:password'),
);
fetch('some_url', {
method: 'GET',
headers: headers,
})
.then(response => response.json())
.then(responseJson => {
console.log('.....', responseJson);
AsyncStorage.setItem(
'ACCESS_TOKEN',
JSON.stringify(responseJson),
err => {
if (err) {
console.log('an error');
throw err;
}
console.log('success');
},
).catch(err => {
console.log('error is: ' + err);
});
try {
const value = AsyncStorage.getItem('ACCESS_TOKEN');
if (value !== null) {
console.log(JSON.parse(value));
}
} catch (error) {}
this.productData = responseJson;
this.isProductLoading = 'done';
})
.catch(error => {
console.error(error);
this.isProductLoading = 'error';
});
};
}
export default new ProductStore();
AsyncStorage.getItem() returns a promise, not the value. So, just add a then block after the line AsyncStorage.getItem('ACCESS_TOKEN');. It would be like this
AsyncStorage.getItem('ACCESS_TOKEN').then(value => {
if (value !== null) {
console.log(JSON.parse(value));
}
}).catch(err => console.error(err));
Still am able to get the accessToken successfully but don't understand why I'm getting auth.getAccessToken is not a function
index.js
$.ajax({
type: "GET",
url: "/getSingRpt",
dataType: "json",
success: function (embedData) {
let reportLoadConfig = {
type: "report",
tokenType: models.TokenType.Embed,
accessToken: embedData.accessToken,
embedUrl: embedData.embedUrl[0].embedUrl
};
tokenExpiry = embedData.expiry;
let report = powerbi.embed(reportContainer, reportLoadConfig);
report.off("loaded");
report.on("loaded", function () {
console.log("Report load successful");
});
report.off("rendered");
report.on("rendered", function () {
console.log("Report render successful");
});
report.off("error");
report.on("error", function (event) {
let errorMsg = event.detail;
console.error(errorMsg);
return;
});
},
error: function (err) {
let errorContainer = $(".error-container");
$(".embed-container").hide();
errorContainer.show();
let errMsg = JSON.parse(err.responseText)['error'];
let errorLines = errMsg.split("\r\n");
let errHeader = document.createElement("p");
let strong = document.createElement("strong");
let node = document.createTextNode("Error Details:");
let errContainer = errorContainer.get(0);
strong.appendChild(node);
errHeader.appendChild(strong);
errContainer.appendChild(errHeader);
errorLines.forEach(element => {
let errorContent = document.createElement("p");
let node = document.createTextNode(element);
errorContent.appendChild(node);
errContainer.appendChild(errorContent);
});
}
});
Server.js
app.get('/getSingRpt', async (req, res) => {
try {
await embedToken.getEmbedParamsForSingleReport().then((result) => {
console.log(result);
res.status(200).send({ success: true, data: result });
})
} catch (e) {
console.error(e);
res.status(400).send({ success: false, message: 'problem in getting report' });
}
});
embedSConfigService.js
async function getEmbedParamsForSingleReport(workspaceId, reportId, additionalDatasetId) {
const reportInGroupApi = `https://api.powerbi.com/v1.0/myorg/groups/${workspaceId}/reports/${reportId}`;
const headers = await getRequestHeader();
const result = await fetch(reportInGroupApi, {
method: 'GET',
headers: headers,
})
console.log('result', result);
if (!result.ok) {
throw result;
}
const resultJson = await result.json();
const reportDetails = new PowerBiReportDetails(resultJson.id, resultJson.name, resultJson.embedUrl);
const reportEmbedConfig = new EmbedConfig();
reportEmbedConfig.reportsDetail = [reportDetails];
let datasetIds = [resultJson.datasetId];
if (additionalDatasetId) {
datasetIds.push(additionalDatasetId);
}
reportEmbedConfig.embedToken = await getEmbedTokenForSingleReportSingleWorkspace(reportId, datasetIds, workspaceId);
return reportEmbedConfig;
}
async function getRequestHeader() {
let tokenResponse;
let errorResponse;
try {
tokenResponse = await auth.getAccessToken();
} catch (err) {
if (err.hasOwnProperty('error_description') && err.hasOwnProperty('error')) {
errorResponse = err.error_description;
} else {
errorResponse = err.toString();
}
return {
'status': 401,
'error': errorResponse
};
}
const token = tokenResponse;
console.log('TOKEN==>', tokenResponse)
return {
'Content-Type': "application/json",
'Authorization': utils.getAuthHeader(token)
};
}
Auth.js
const adal = require('adal-node');
const config = require(__dirname + '/../config/config.json');
const getAccessToken = () => {
return new Promise((resolve, reject) => {
try {
const authMode = config.authenticationMode.toLowerCase();
const AuthenticationContext = adal.AuthenticationContext;
let authorityUrl = config.authorityUri;
if (authMode === 'masteruser') {
new AuthenticationContext(
authorityUrl,
).acquireTokenWithUsernamePassword(
config.scope,
config.pbiUsername,
config.pbiPassword,
config.clientId,
(err, token) => {
if (err) reject(err);
resolve(token);
},
);
} else if (authMode === 'serviceprincipal') {
authorityUrl = authorityUrl.replace('common', config.tenantId);
new AuthenticationContext(
authorityUrl,
).acquireTokenWithClientCredentials(
config.scope,
config.clientId,
config.clientSecret,
(err, token) => {
if (err) reject(err);
resolve(token);
},
);
} else {
reject(new Error('Unknown auth mode'));
}
} catch (err) {
console.error(err);
reject(err);
}
});
};
getAccessToken()
.then((token) => console.log(token))
.catch((err) => console.error(err));
updated
utilities.js
let config = require(__dirname + "/../config/config.json");
function getAuthHeader(accessToken) {
// Function to append Bearer against the Access Token
return "Bearer ".concat(accessToken);
}
Could you help me to figure this out.
I need to refresh my token on error and retry failed requests..
I have:
axios.interceptors.response.use(function(response) {
return response;
}, function(error) {
const originalRequest = error.config;
if(error.response.status===401 && !originalRequest._retry) {
originalRequest._retry = true;
setTimeout(async function() {
const refreshedHeader = await setHeader()
console.log('New header: ', refreshedHeader)
axios.defaults.headers = refreshedHeader
originalRequest.headers = refreshedHeader
console.log('Original Request: ', originalRequest)
return axios(originalRequest)
}, 2000);
}
return Promise.reject(error);
});
setHeader() is this:
const setHeader = async () => {
const token = await refreshToken()
const header = {
Authorization: `Bearer ${token}`,
};
return header
}
The new token is pulled and the header is updated, but the retry fails with 401 still?
It is because of the timeout. This:
return Promise.reject(error);
will always return an error before the timeout has done its job.
Try to remove that timeout and set the error function to async.
axios.interceptors.response.use(function(response) {
return response;
}, async function(error) {
const originalRequest = error.config;
if (error.response.status===401 && !originalRequest._retry) {
originalRequest._retry = true;
const refreshedHeader = await setHeader()
console.log('New header: ', refreshedHeader)
axios.defaults.headers = refreshedHeader
originalRequest.headers = refreshedHeader
console.log('Original Request: ', originalRequest)
return axios(originalRequest);
}
return Promise.reject(error);
});
Else if necessary try something like:
axios.interceptors.response.use(function(response) {
return response;
}, async function(error) {
await new Promise(function(res) {
setTimeout(function() {res()}, 2000);
});
const originalRequest = error.config;
if (error.response.status===401 && !originalRequest._retry) {
originalRequest._retry = true;
const refreshedHeader = await setHeader()
console.log('New header: ', refreshedHeader)
axios.defaults.headers = refreshedHeader
originalRequest.headers = refreshedHeader
console.log('Original Request: ', originalRequest)
return axios(originalRequest);
}
return Promise.reject(error);
});
This will block all of the rest for 2 seconds and then resolve or reject it.
I have to functions called: getMatchDataApi() and saveApiDataToDb(). getMatchDataApi() function returns value from an api and saveApiDataToDb() function is used to store getMatchDataApi() value into firestore database.
function getMatchDataApi() {
var options = {
method: "GET",
hostname: "dev132-cricket-live-scores-v1.p.rapidapi.com",
port: null,
path: "/scorecards.php?seriesid=2141&matchid=43431",
headers: {
"x-rapidapi-host": "dev132-cricket-live-scores-v1.p.rapidapi.com",
"x-rapidapi-key": "63e55e4f7fmsh8711fb1c0bd9ec2p1d8b4bjsne2b8db0a1a82"
},
json: true
};
var req = http.request(options, res => {
var chunks = [];
res.on("data", chunk => {
chunks.push(chunk);
});
res.on("end", () => {
var body = Buffer.concat(chunks);
var json = JSON.parse(body);
playerName = json.fullScorecardAwards.manOfTheMatchName;
console.log("player name", playerName);
});
});
req.end();
}
async function saveApiDataToDb() {
await getMatchDataApi();
var name = playerName;
console.log("Aman Singh", name);
}
Here i am using async function. So that first i want it should execute this getMatchDataApi() first and returns the value and after that it should print value inside this function saveApiDataToDb().
And then i am calling saveApiDataToDb() as follow:
exports.storeMatchData = functions.https.onRequest((request, response) => {
saveApiDataToDb()
});
Yes, you can use async/await in cloud functions. But, you can't access/fetch the data outside the google servers in the Spark Plan (Free Plan).
Hope this helps.
Modify your functions/index.js file like this way:
const functions = require('firebase-functions');
const request = require('request');
exports.storeMatchData = functions.https.onRequest( async (req, res) => {
let body = '';
await getMatchDataApi().then(data => body = data).catch(err => res.status(400).end(err));
if (!body) {
return res.status(404).end('Unable to fetch the app data :/');
}
// let json = JSON.parse(body);
// playerName = json.fullScorecardAwards.manOfTheMatchName;
// console.log("Aman Singh", playerName);
res.send(body);
});
function getMatchDataApi() {
const options = {
url: 'https://dev132-cricket-live-scores-v1.p.rapidapi.com/scorecards.php?seriesid=2141&matchid=43431',
headers: {
"x-rapidapi-host": "dev132-cricket-live-scores-v1.p.rapidapi.com",
"x-rapidapi-key": "63e55e4f7fmsh8711fb1c0bd9ec2p1d8b4bjsne2b8db0a1a82"
},
};
return cURL(options);
}
function cURL(obj, output = 'body') {
return new Promise((resolve, reject) => {
request(obj, (error, response, body) => {
if (error)
reject(error);
else if (response.statusCode != 200)
reject(`cURL Error: ${response.statusCode} ${response.statusMessage}`);
else if (response.headers['content-type'].match(/json/i) && output == 'body')
resolve(JSON.parse(body));
else if (output == 'body')
resolve(body);
else
resolve(response);
});
});
}
I try to solve my issue using promise in cloud functions. so it could help someone.
This is my cloud function
exports.storeMatchData = functions.https.onRequest((request, response) => {
a().then(
result => {
saveApiDataToDb(result);
},
error => {}
);
});
This is the function from which i am calling api and resolving its data first what i want
var options = {
method: "GET",
hostname: "dev132-cricket-live-scores-v1.p.rapidapi.com",
port: null,
path: "/scorecards.php?seriesid=2141&matchid=43431",
headers: {
"x-rapidapi-host": "dev132-cricket-live-scores-v1.p.rapidapi.com",
"x-rapidapi-key": "63e55e4f7fmsh8711fb1c0bd9ec2p1d8b4bjsne2b8db0a1a82"
},
json: true
};
var options1 = {
method: "GET",
hostname: "dev132-cricket-live-scores-v1.p.rapidapi.com",
port: null,
path: "/matches.php?completedlimit=5&inprogresslimit=5&upcomingLimit=5",
headers: {
"x-rapidapi-host": "dev132-cricket-live-scores-v1.p.rapidapi.com",
"x-rapidapi-key": "63e55e4f7fmsh8711fb1c0bd9ec2p1d8b4bjsne2b8db0a1a82"
}
};
var a = function getMatchDataApi() {
// Return new promise
return new Promise((resolve, reject) => {
// Do async job
let firstTask = new Promise((resolve, reject) => {
var req = http.request(options, res => {
var chunks = [];
var arr = [];
res.on("data", chunk => {
chunks.push(chunk);
});
res.on("end", () => {
var body = Buffer.concat(chunks);
var json = JSON.parse(body);
const playerName = json.fullScorecardAwards.manOfTheMatchName;
resolve(playerName);
});
});
req.end();
});
let secondTask = new Promise((resolve, reject) => {
var req = http.request(options1, res => {
var chunks = [];
var arr = [];
res.on("data", chunk => {
chunks.push(chunk);
});
res.on("end", () => {
var body = Buffer.concat(chunks);
var json = JSON.parse(body);
const playerName = json;
resolve(playerName);
});
});
req.end();
});
Promise.all([firstTask, secondTask]).then(
result => {
resolve(result);
},
error => {
reject(error);
}
);
});
};
This is the function in which I am going to use getMatchDataApi() values after resolving in this function.
function saveApiDataToDb(data) {
console.log("Name of player", data[0]);
}