I'm unable to access the result of my query despite checking in browser network(xhr) and seeing the data is returned successfully from api. But I can't even console.log the returned data. Not sure what's going on.
Here's my code:
// const url='/../../_public/api/news.php'; // does not work
const url='https://jsonplaceholder.typicode.com/users/3' // works
let getHandle = () => {
return new Promise(function (resolve){
$.get(url, {endpoint: 'titles', param: 'titles'}, (response) => {
console.log(response);
resolve(response);
})
})
}
getHandle().then((res) => {
console.log(res);
})
<script src="https://code.jquery.com/jquery-3.6.3.min.js"></script>
The problem is your api url, you need to start the local dev server with your PHP backend and change the url to something like '/api/news.php'
// I tested your code with the json placeholder API and it works
Related
I've got the following JS which is attempting to return a value from an AWS API Gateway:
<script>
fetch("https://myapi/get")
.then(response => response.json())
.then(data => {
document.getElementById("website-counter").innerHTML = data.body
});
</script>
The API GW triggers a lambda function to get a value from a DynamoDB table.
Im attempting to display the retuned value by
<p>
CV Website Views: <span id="website-counter"></span><br/>
</p>
However, the "website-counter" returns an undefined value, not the required DB value.
Also, Ive set the CORS headers in the Lambda function itself. If i access the direct link to the API from AWS console, i get the retuned value from dynamodb as expected.
This post resolved the issue for me: ES6 fetch function returns undefined
This is now working fine:
<script type ="text/javascript">
function visitcount() {
return fetch("https://myapi/get").then(function(response) {
return response.json();
}).then(function(json) {
return json;
});
}
visitcount().then(function(result) {
document.getElementById("website-counter").innerHTML = result
console.log(result);
});
</script>
I'm working on a project where we're using unity to build a webgl enabled application for use in a browser.
Because of some issues surrounding authentication and cookies we're having to use a .jslib plugin to map some of the unity calls to javascript calls in the website's code.
The code mapping between the two applications is working fine, but I'm running into a async issue in one of the plugin functions
I'm working on the following plugin code map:
AuthenticatedGet: function (uri) {
var uriString = Pointer_stringify(uri)
var result = authenticatedGetRequest(uriString)
var buffer = _malloc(lengthBytesUTF8(result) + 1)
writeStringToMemory(result, buffer)
return buffer
},
Which calls the following function in the website codebase:
function authenticatedGetRequest(uri) {
let endpoint = wpApiSettings.root + uri
$.ajax({
url: endpoint,
method: "GET",
beforeSend: function (xhr) {
xhr.setRequestHeader("X-WP-Nonce", wpApiSettings.nonce)
},
data: {},
})
.done((response) => {
// ? do we need to stringify?
return JSON.stringify(response)
})
.fail((error) => {
console.error(error)
return error
})
}
The problem comes in the plugin's call to authenticatedGetRequest. Since that function contains a promise I need to wait for the async call to finish.
I tried rewriting the code to return and handle the promise:
Plugin code:
AuthenticatedGet: function (uri) {
var uriString = Pointer_stringify(uri)
var result = authenticatedGetRequest(uriString).then((response) => {
var buffer = _malloc(lengthBytesUTF8(result) + 1)
writeStringToMemory(result, buffer)
return buffer
})
},
Website code:
function authenticatedGetRequest(uri) {
let endpoint = wpApiSettings.root + uri
return $.ajax({
url: endpoint,
method: "GET",
beforeSend: function (xhr) {
xhr.setRequestHeader("X-WP-Nonce", wpApiSettings.nonce)
},
data: {},
})
.done((response) => {
// ? do we need to stringify?
return JSON.stringify(response)
})
.fail((error) => {
console.error(error)
return error
})
}
But doing this causes a build error on the unity side:
I should note that if I fake out the response on the website side by immediately returning with a string (removing the async nature of the call), everything works fine.
I'm pretty new to unity and c# in general so I'm not sure where I'm going wrong here. Any ideas?
I'm using Cypress to do some API testing, but I am struggling to access values in the JSON response body; however I can perform assertions against the body which suggests it's receiving it correctly.
Below I am trying to assign the JSON body (response.body) and then get the value of 'id' out of it:
describe('Creating a board', () => {
it('should create a board', () => {
cy.request({
method : 'POST',
url:`${requestUrl}/boards/`,
qs: {
name : "test-board",
token : token,
key : key
}
}).then((response) => {
expect(response).property('status').to.equal(200)
expect(response.body).property('id').to.not.be.oneOf([null, ""])
const body = (response.body)
boardId = body['id']
})
})
I've done numerous searches and can't find a concrete way to do it. Any help would be appreciated...
I managed to solve this by using a Promise;
Doing some further reading, I found out the then function I am executing is synchronous (I'm new to JS, pls don't hurt me).
I refactored the then function to the following:
.then((response) => {
return new Promise(resolve => {
expect(response).property('status').to.equal(200)
expect(response.body).property('id').to.not.be.oneOf([null, ""])
const respBody = response.body;
boardId = respBody['id']
resolve(boardId)
})
It's probably not entirely correct or best practice, but it will do for my demo
Although not needed anymore as you found a workaround, I've looked into my cypress code. I was able to access properties of response body followingly:
cy.request({
...
}.its('body').then((body) => {
const whatever = body.whatever;
})
I believe it basically works the same as your workaround - waiting to resolve body in a promise.
I was able to do it in the following way:
cy.request(
'POST',
url,
payload()).then((response) => {
expect(response.body).to.have.property('ReturnCode', 'Success')
expect(response.body).to.have.property('ReturnText', 'Success')
expect(response.body).to.have.property('PaymentInstructionId')
paymentID = response.body.PaymentInstructionId
})
paymentID is the variable that is filled with the value that i want from the repply.
When I call the URL, an undefined number of requests are sent.
Now I try to find out if one of the requests contains a certain payload.
cy.server();
cy.visit(url);
cy.route({
method: 'POST',
url: '**/t/e/**',
}).as('xhrRequest');
I have found a similar approach on How to capture all API calls in cypress? so far.
the problem here is that a fixed number of API calls is assumed.
cy.wait(Array(60).fill('#xhrRequest'), { timeout: 30000 }).then((xhrs) => {
xhrs.forEach((res) => {
expect(res.status).not.to.be.null
})
})
How do I get it that all requests are intercepted and fail my test if there is not a single request containing the payload.
I already wrote something like this in puppeteer
let hasSpecialRequest = false;
page.on('request', request => {
if (isSpecialRequest(request)) {
hasSpecialRequest = true;
}
request.continue();
});
await page.setRequestInterception(true);
expect(hasSpecialRequest).to.equal(true);
The system checks whether each request is one of the special requests and sets the variable accordingly. Something like this I try to recreate with Cypress.
You might consider doing cy.exec and run a script in another language and return status from subprocess.
I may have misunderstood the problem but since I got here through my Google expedition maybe this might help someone that had my problem and possibly you.
At first I used the cy.wait(#alias) but could never retrieve all the responses (only one response was being shown and I couldn't figure out how to access ALL the responses). So I ended up immediately storing the responses into another array to access within the test.
let xhrRequests;
function getXhrRequests() {
xhrRequests = [];
cy.intercept('GET', '**', (res) => {
xhrRequests.push(res);
});
return xhrRequests;
}
describe('Some', function () {
it('Thing 1', () => {
let thing1 = getXhrRequests();
cy.visit('http://some.site');
thing1.forEach((res) => {
expect(res.status).not.to.be.null;
})
}
it('Thing 2', () => {
let thing2 = getXhrRequests();
cy.visit('http://some.site/2');
thing2.forEach((res) => {
expect(res.status).not.to.be.null;
})
}
});
I'm fetching data from a API that returns a JSON object:
fetch("api.php")
.then(function(response) {
console.log("Status: " + response.status);
if (response.ok) {
return response.json();
} else {
throw Error(response.status);
}
}).then(function(json) {
json.forEach(function(item) {
// 'datas' contains the items extracted from the JSON response
datas.add(item);
});
}).catch(function(err) {
console.log(error);
});
If I want to query the data with jinqJs I can change the code slightly to:
}).then(function(json) {
var result = new jinqJs()
.from(json)
.where('start_date = 2017-03-10')
.select();
result.forEach(function(item) {
datas.add(item);
});
}).catch(function(err) {
and it works really well.
My question is: due to the fact that by fetching only once the API I actually download ALL the needed data how can I query it 'outside' the forEach fetch?. I mean: I already have all the data with one call to the API, I can easily do queries on the data with jinqJs why should I call the API every time I need to query it? Is it possible to query datas once the forEach has added all the items?
For example, outside the forEach (notice the .from(datas) instead of .from(json)) I could do:
var result = new jinqJs()
.from(datas)
.where('start_date = 2017-03-10')
.select();
and get the same result.
As I'm trying to build a mobile app, this would be handy because I would bind the above code to specific buttons and query the data accordingly and I would connect to the internet only the first time the app is started rather than every time a query is needed.
Assign the "JSON" promise to a variable
var something = fetch("api.php")
.then(function(response) {
console.log("Status: " + response.status);
if (response.ok) {
return response.json();
} else {
throw Error(response.status);
}
});
Now you can use something as many times as you like
something
.then(json => console.log(json))
.catch ...
something.then(json => new jinqJs()
.from(json)
.where('start_date = 2017-03-10')
.select()
.forEach(function(item) {
datas.add(item);
});
).catch ....