Extract the price only from api using node-fetch array - javascript

I am sorry for a basic question, I have been trying to extract only the price using node-fetch from API
const fetch = require('node-fetch');
fetch('https://api.binance.us/api/v3/avgPrice?symbol=DOGEUSD')
.then(res => res.text())
.then(text => console.log(text))
let AvgPrice = text.map(text => text.price);
The error I am receiving is
internal/modules/cjs/loader.js:968
throw err;
^
Please, any suggestion is greatly appreciated

There are several things that you need to check out
Errors reagarding cjs/loader.js have little or nothing to do with your code per se but rather the setup, for example how you run the code, naming of the file, etc,
internal/modules/cjs/loader.js:582 throw err
https://github.com/nodejs/help/issues/1846
This code will return Reference error: text is not defined.
The reason is that you never define the variable text and then you try to call map function on it.
Also fetch is a async function and nodejs is single threaded non-blocking. So what happens is that you send a http request (fetch) to the website, that takes times, but meanwhile your coding is still running, so continues to the next line in your code.
Lets add some console logs
const fetch = require('node-fetch');
console.log('1. lets start')
fetch('https://api.binance.us/api/v3/avgPrice?symbol=DOGEUSD')
.then(res => res.text())
.then(text => {
console.log('2. I got my text', text)
})
console.log('3. Done')
You might think that this will log out
lets start
I got my text {"mins":5,"price":"0.4998"}
Done
Nopes, it will log out
Lets start
Done
I got my text {"mins":5,"price":"0.4998"}
Because you fetched the data, then your program continued, it looged out 3. Done and THEN when it got the data from api.binance it logged out 2. I got my text (notice the keyword then, it happens later)
map is a function for arrays. What the api returns is an object. So when you fix your async code, you will get TypeError text.map is not a function
Since it returns an object you can access it's property right away text.price

Related

How to wait for requests and validate responses using playwright?

This is my first time using playwright and I can't figure out how to wait for requests and validate responses.
I've been using cypress for a quite a long time, and it was pretty easy to manage network requests.
For example, I need to validate response after clicking a button and this is how I would do it with cypress:
cy.server()
cy.route('POST', '/api/contacts').as('newContact')
cy.get('.btn').click()
cy.wait('#newContact').then((response) => {
expect(response.status).to.eq(400)
expect(response.responseBody.data.name).to.eq('abcde')
})
And this is how I'm trying to do the same thing with playwright, but it validates GET request that was sent long before it even clicked save button. I can't figure out how to manage this request properly and that's a show stopper for my test suite:
await contacts.clickSaveBtn()
await page.waitForResponse((resp) => {
resp.url().includes('/api/contacts')
expect(resp.status()).toBe(400)
})
Any help or advice would be really appreciated
What you need to do is first start waiting for the response and then click, so the waitForResponse() can catch the actual response coming as a result of the click.
await Promise.all([
page.waitForResponse(resp => resp.url().includes('/api/contacts') && resp.status() === 400),
contacts.clickSaveBtn()
]);
This should handle the possible race condition.
Alternatively, you can assign a promise, then later wait for it:
const responsePromise = page.waitForResponse(resp => resp.url().includes('/api/contacts') && resp.status() === 400);
await contacts.clickSaveBtn();
const response = await responsePromise;
It's more readable and you get the response value.

Dark magic going through res.json()

To avoid the XY problem, here's my final goal: I want to fetch something, use the response body, and return the response (from which the user should be able to get the body) without returning the body separately. On the paper, this should work:
const res = await fetch("something")
const clone = res.clone()
const body = await clone.json()
// Use body
return res
If I get lucky, the process ends during await clone.json(). If I don't, it freezes. Forever.
As a reminder, res.json can't be called twice.
Does it think I'm not good enough to get an error message? Any help on that? Thank you.
Progess
I located the error: in node_modules/node-fetch/lib/index.js:416, the listener on the end of the action is never triggered. I still don't know why.
When replacing the URL with "https://jsonplaceholder.typicode.com/todos/1", everything works. This may be related to the server. I don't see any link between the origin of the request and whether the request could be cloned...
Placing res.text() before clone.json() magically fixes it, but it makes everything lose its purpose.
By messing with the module's code, I found that the response actually never ends. The JSON gets cut, and the chunk from the last data event call isn't the end of the JSON, so the end event never gets called. Extremely confusing.
I spent too much time on this issue, I will simply avoid it by returning the body separately.
This seems to work just fine
const myFetch = async (url) => {
const resp = await fetch(url),
clone = resp.clone()
json = await clone.json()
console.log('inner:', json.title)
return resp
}
myFetch('https://jsonplaceholder.typicode.com/todos/1')
.then(resp => resp.json())
.then(json => console.log('outer:', json.title))

Async API call inside an infinite while loop using Axios in NODE JS

Let me begin by saying that I am a beginner to Asynchronous JavaScript and it took me quite a while to wrap my head around the concept.
Now, coming to the situation at hand. I wanted to write a code that would automatically detect text from a folder containing multiple screenshots using an OCR API, whose documentation can be found here : https://ocr.space/OCRAPI
The OCR uses two engines which can produce different results. The code should run with the default engine specified and display the contents. If the result is satisfactory, the user can chose to move on with the next screenshot, or make another api request with a different engine.
I tried to use an infinite while loop to achieve this:
const fs = require("fs")
const imageToBase64 = require("image-to-base64")
const apikey = "helloworld"
let engine = 1
fs.promises
.readdir("./screenshots")
.then((files) => {
for (const file of files) {
while (true) {
console.log("Making an API Request")
imageToBase64("./screenshots/" + file)
.then((res) => {
const form = new FormData()
form.append("base64Image", "data:image/jpeg;base64," + res)
form.append("OCREngine", engine)
axios
.post("https://api.ocr.space/parse/image", form, {
headers: { apikey, ...form.getHeaders() },
})
.then((response) => {
console.log(response.data.ParsedResults[0].ParsedText)
/*Code to ask the user whether the result is satisfactory or not.
if yes, break out of the while loop, otherwise change the engine and make the request again*/
engine = 2
})
.catch((error) => console.log(error))
})
.catch((error) => console.log(error))
}
}
})
.catch((error) => console.log(error))
The infinite while loop appears to continue the execution and not wait for the user input.
Can anyone help me out with the correct method of implementing this idea?

I'm getting a 422 error for a function that works

I'm building a bucket-list application, and I've included a function to allow users to delete items/documents from their bucket list/the database. When the function is called, I receive an HTTP 422 Unprocessable Entity error, leading me to believe the function does not work. However, when I refresh the page, the data has been successfully deleted from the database.
Here is the function for deleting the item on the list (the document from the database):
handleDelete = id => {
API.deleteItemFromList(this.props.match.params.id)
.then(res => console.log(res.data))
.catch(err => console.log(err));
};
And here is the code for the api:
deleteItemFromList: function(id) {
return axios.delete("/api/bucketList/" + id);
}
};
So basically, the function does work, but it doesn't work, and I don't understand why. And I'd like to be able to delete the item from the list without getting any error at all.
I'm pretty sure I've supplied all the necessary code, but if I've left something out, or if there's something else you need or would like to see, let me know.
Many thanks in advance!
The error you're getting is TypeError: req.json is not a function. You'll need to change req.json to res.json.
It's the small stuff that'll get ya.

Can't seem to save the output of a client.shell() command to a variable

I am using node-webkit and ADBkit to attempt to read a line from an android build.prop and do something depending on what that line is.
full script at http://pastebin.com/7N7t1akk
The gist of it is this:
var model = client.shell(devices, "su -c 'grep ro.product.model /system/build.prop'" );
alert(model)
i want to read ro.product.model from build.prop into the variable model
As a test im simply attempting to create an alert that displays the return of this shell command, in my case ro.product.model=KFSOWI but whenever i run this script with a connected device the alert returns object Object
edit**
Ive just realized that client.getProperties(serial[, callback]) would probably work better but dont understand these functions (specifically callback) very well
I am very new to this area of Javascripting and home someone can offer some insight
JavaScript is asynchronous programming language, it is built on callbacks. Every function should have callback with data passed to it, if you will watch on documentation, you have client.shell(serial, command[, callback]) so data from executing client.shell() will be passed to callback. You should assign some function that will process callback, for your case will be this
client.shell(devices, "su -c 'grep ro.product.model /system/build.prop'", function(data) {
console.log(data);
});
P.S. there is no alert in nodejs
According to the documentation, you can catch the output in the 2nd argument of client.shell()'s callback:
client.shell(devices, "su -c 'grep ro.product.model /system/build.prop'", function(err, output) {
if (err) {
console.log(err);
}
console.log(output);
});
Use async / await for clearer code.
const data = await client.shell(devices, "su -c 'grep ro.product.model /system/build.prop'" );
console.log(data); // => "Samsung.TM395"
Of course, this only will work if this code is in an async function.
Streamed data.
For streamed data with adbkit, you will need to do a little more to read the entire stream and then output the results, like so:
const stream = await adbClient.shell( config.udid, "ime list -s" ) // adb command to list possible input devices (e.g. keyboards, etc.).
const result = await adb.util.readAll( stream );
console.log( result.toString() ); // => com.sec.android.inputmethod/.SamsungKeypad

Categories