data output after receiving it in fetch - javascript

I apologize for the stupid question, please tell me how to transfer data from fetch (). then () to another function.
const http = require('http');
const https = require('https');
var urlZaprosHttp = 'http://ietf.org/';
var urlZaprosHttps = 'https://ietf.org/';
const fetch = url => new Promise((resolve, reject) => {
const protocol = url.startsWith('https') ? https : http;
protocol.get(url, res => {
if (res.statusCode !== 200) {
const { statusCode, statusMessage } = res;
reject(new Error(`Status Code: ${statusCode} ${statusMessage}`));
}
res.setEncoding('utf8');
const lines = [];
res.on('data', chunk => lines.push(chunk));
res.on('end', () => resolve(lines.join()));
});
});
// Usage
fetch(urlZaprosHttps)
.then(body => console.log(body))
.catch(err => console.error(err));

You can just simply call another function from within then() and do whatever you want with your data in that function:
fetch(urlZaprosHttps)
.then(body => someOtherFunction(body))
.catch(err => console.error(err));

const myFunc = (data) => {
console.log(data)
}
fetch(urlZaprosHttps)
.then(myFunc(data))
.catch(err => console.error(err));
In the then you can pass in a function and the data returned will be passed to that function, like in my example.

Related

How to mock https.get with Jest

I have a function that calls https.get inside a promise which I want to test with Jest.
The function is like this:
const request = (url) => {
return new Promise((resolve, reject) => {
const chunks = [];
https.get(url, (stream) => {
stream
.on('data', (chunk) => {
if( chunk ) {
chunks.push(JSON.parse(chunk));
}
})
.on('error', (err) => {
reject(err);
})
.on('end', () => {
const data = doSomething(chunks);
resolve(data)
});
});
})
}
I want to test that when the function resolves on "end" and rejects on "error";
Currently I have a test like this but because .on("end") doesn't get called, the promise never resolves.
describe("request", () => {
it("Should resolve", async (done) => {
const response = await request("my-url");
expect(response).toEqual("some-data")
})
})
How can I mock events like .on("end") to be called and ensure the promise resolves?
You can do something like this.
// ./request.test.js
jest.mock('https', () => ({
methodToMock: {}
}));
const Stream = require('stream');
const request = require("./request");
const httpsMock = require("https");
describe("request", () => {
it("Should resolve", async () => {
var streamStream = new Stream()
httpsMock.get = jest.fn().mockImplementation((url, cb) => {
cb(streamStream)
streamStream.emit('data', 'some');
streamStream.emit('data', '-');
streamStream.emit('data', 'data');
streamStream.emit('end'); // this will trigger the promise resolve
})
const response = await request("my-url");
expect(response).toEqual("some-data");
})
})
const https = require("https");
const request = (url) => {
return new Promise((resolve, reject) => {
const chunks = [];
https.get(url, (stream) => {
stream
.on('data', (chunk) => {
if (chunk) {
// chunks.push(JSON.parse(chunk));
chunks.push(chunk);
}
})
.on('error', (err) => {
reject(err);
})
.on('end', () => {
// const data = doSomething(chunks);
const data = chunks.join('');
resolve(data)
});
});
})
}
module.exports = request;
Note that jest.mock('https', ...) need to be called before const request = require("./request"); if you want https to be mocked.

JS read file onload returns undefined

I want to read a TXT file from a directory, I have this code which works fine
window.onload = () => {
fetch("file.txt")
.then(res => res.text())
.then(data => {
console.log(data);
});
};
But I want to exe the fetch call in a function like so:
window.onload = () => {
const filePath = "file.txt";
const fileData = readDataFile(filePath);
console.log(fileData);
};
const readDataFile = path => {
fetch(path)
.then(res => res.text())
.then(data => {
return data;
});
};
But in this case, it returns undefined.
Another problem with it, is I can't catch if an error occurs, I tried adding catch to the promise and throw an error but it does not work. This is what I've tried:
window.onload = () => {
fetch("file.txt")
.then(res => res.text())
.then(data => {
console.log(data);
})
.catch(err => {
throw new Error("ERROR!");
});
};
THANKS :)
This works:
const readDataFile = async path => {
try {
const response = await fetch(path);
const data = await response.text();
return data;
} catch (err) {
console.log('Cannot read file.');
}
}
window.onload = async () => {
const filePath = 'data.txt';
const fileData = await readDataFile(filePath);
console.log(fileData);
}
But again, the catch method does not work ? am I doing it wrong ?

Promises resolving in wrong order

I am playing with promises and modified a script from Medium.
When I run the script it prompts for the code then displays the json data before I can input a value. I then input a value without the prompt for the script to exit.
How can I get the input before the API call works?
'use strict'
const request = require('request')
const readline = require('readline')
let userDetails
const getInput = prompt => new Promise( resolve => {
const io = { input: process.stdin, output: process.stdout }
const read = readline.createInterface(io)
read.question(`${prompt}: `, data => {
console.log(data)
read.close()
resolve(data)
})
})
const getData = () => new Promise( (resolve, reject) => {
const options = {
url: 'https://api.github.com/users/marktyers',
headers: {
'User-Agent': 'request'
}
}
// Do async job
request.get(options, (err, resp, body) => {
if (err) reject(err)
else resolve(JSON.parse(body))
})
})
function main() {
const GitHubAPICall = getData()
const getBase = getInput('input base currency')
GitHubAPICall
.then(result => {
userDetails = result
console.log('Initialized user details')
console.log(userDetails)
}).then(getBase)
.catch(err => console.log(err))
}
main()
In your main function, you can do it like that:
function main() {
const GitHubAPICall = getData; // WITHOUT ()
const getBase = getInput; // Those 2 declarations are useless, btw
GitHubAPICall()
.then(result => {
userDetails = result
console.log('Initialized user details')
console.log(userDetails)
})
.then(() => getBase())
.then(data => // Do something with the data returned by 'getInput')
.catch(err => console.log(err))
}

Node.js - Mock result of a promise

I want to mock the result of a function within a node module so that i can run assertions.
Considering the following node module:
const doPostRequest = require('./doPostRequest.js').doPostRequest;
const normalizeSucessResult = require('./normalizer.js').normalizeSucessResult;
const normalizeErrorResult = require('./normalizer.js').normalizeErrorResult;
exports.doPost = (params, postData) => {
return doPostRequest(params, postData).then((res) => {
const normalizedSuccessResult = normalizeSucessResult(res);
return normalizedSuccessResult;
}).catch((err) => {
const normalizedErrorResult = normalizeErrorResult(err);
return normalizedErrorResult;
})
}
The function doPostRequest returns a promise. How can i fake the return value of this promise so that i can assert if normalizeSucessResult has been called?
So for i have tried:
const normalizeSucessResult = require('./normalizer.js');
const doPostRequest = require('./doPostRequests.js');
const doPost = require('./doPost.js');
it('runs a happy flow scenario', async () => {
let normalizeSucessResultStub = sinon.stub(normalizeSucessResult, 'normalizeSucessResult');
let postData = { body: 'Lorum ipsum' };
let params = { host: 'someUrl', port: 433, method: 'POST', path: '/' };
sinon.stub(doPostRequest, 'doPostRequest').resolves("some response data"); //Fake response from doPostRequest
return doPost.doPost(params, postData).then((res) => { //res should be equal to some response data
expect(normalizeSucessResultStub).to.have.been.calledOnce;
expect(normalizeSucessResultStub).to.have.been.with("some response data");
});
});
The doPostRequest module looks like this:
const https = require('https')
module.exports.doPostRequest = function (params, postData) {
return new Promise((resolve, reject) => {
const req = https.request(params, (res) => {
let body = []
res.on('data', (chunk) => {
body.push(chunk)
})
res.on('end', () => {
try {
body = JSON.parse(Buffer.concat(body).toString())
} catch (e) {
reject(e)
}
resolve(body)
})
})
req.on('error', (err) => {
reject(err)
})
if (postData) {
req.write(JSON.stringify(postData))
}
req.end()
})
}
You can use Promise.resolve to return a promise with any given value.
Promise.resolve(“hello world”);
For stub your func you need to do like this
sinon.stub({doPostRequest}, 'doPostRequest').resolves("some response data")
Okay, i figured it out. The function doPostRequest was loaded using require, on the top of the file using const doPostRequest = require('./doPostRequest.js').doPostRequest;
In order to mock the data that comes back from a function that is loaded using require i had to use a node module called mock-require. There are more modules that can take care of this (proxyquire is a populair one) but i picked mock-require (i did not have a specific reason for choosing mock-require).
For anyone else that is stuck with a similar problem, try mock-require to mock the respose from files that are loaded using require.

Writing a generic HTTP request in NodeJS

I am making an app that creates multiple HTTP requests to different APIs, and would like to abstract the "sending" and "getting" portion of the data into a utility function that can be exported. It should be async. So far, I have created the following, but it won't work since request.end() needs to be declared somewhere, and I'm stuck here. Thanks!
Note: the resulting data should be able to be easily returned to some other function on order to do other work with it later on.
exports.handleHttpRequests = (url) => {
return new Promise((resolve, reject) => {
const request = http.request(url, response => {
let chunks = [];
res.on('data', chunk => {
chunks.push(chunk);
});
res.on('end', () => {
let body = Buffer.concat(chunks).toString();
resolve(body);
})
})
}).then(data => {
return data;
});
}
Hey you already done all, just call request.end() inside your new Promise callback & also handle error . And do what you want to do with resolve ,reject.
exports.handleHttpRequests = (url) => {
return new Promise((resolve, reject) => {
const request = http.request(url, res => {
let chunks = [];
res.on('data', chunk => {
chunks.push(chunk);
});
res.on('end', () => {
let body = Buffer.concat(chunks).toString();
resolve(body);
})
});
//handling error
request.on('error', (e) => {
reject('problem with request: ' + e.message);
});
//here you have to put request.end()
request.end();
})
};

Categories