Promises with http.get node.js - javascript

Im am doing nodeschool exercises , the
This problem is the same as the previous problem (HTTP COLLECT) in
that you need to use http.get(). However, this time you will be
provided with three URLs as the first three command-line arguments.
You must collect the complete content provided to you by each of the
URLs and print it to the console (stdout). You don't need to print out
the length, just the data as a String; one line per URL. The catch is
that you must print them out in the same order as the URLs are
provided to you as command-line arguments.
in other words , i am to register 3 http.get request , and print data recieved from it in order.
I am trying to do it with promises = another get request wont be called untill the first on didnt end.
My code looks like this
var http=require("http");
var collect=[];
var dat=[];
for( var i = 2 ; i < process.argv.length;i++){
collect.push(process.argv[i]);
}
function chainIt(array,callback){
return array.reduce(function(promise,item){
return promise.then(function(){
return callback(item)
})
},Promise.resolve())
}
function getIt(item){
return http.get(item,function(response){
response.on("data",function(data){
dat.push(data);
})
})
}
chainIt(collett,function(item){
return getIt(item)
})
}).then(function(){
collect.forEach(function(x){
console.log(x);
})
})
But i actually print no data = i fail the exercise.
I do not see any bug here , but im just starting with promises and node. Where is the mistake?

For educational purposes, I recently wrote a wrapper for the http and https modules that uses native Promises. That said, I recommend using a library, such a request; that makes things simpler, has unit test coverage, as is maintained by the open source community. Also, my wrapper does a naive string concatenation with the response chunks, which I'm not convinced is the most performant way of building up the response body.
FYI: this requires Node.js 4 or above, although the methodology is pretty much the same in Node 0.x.x.
'use strict';
const http = require('http');
const url = require('url');
module.exports = {
get(url) {
return this._makeRequest('GET', url);
},
_makeRequest(method, urlString, options) {
// create a new Promise
return new Promise((resolve, reject) => {
/* Node's URL library allows us to create a
* URL object from our request string, so we can build
* our request for http.get */
const parsedUrl = url.parse(urlString);
const requestOptions = this._createOptions(method, parsedUrl);
const request = http.get(requestOptions, res => this._onResponse(res, resolve, reject));
/* if there's an error, then reject the Promise
* (can be handled with Promise.prototype.catch) */
request.on('error', reject);
request.end();
});
},
// the options that are required by http.get
_createOptions(method, url) {
return requestOptions = {
hostname: url.hostname,
path: url.path,
port: url.port,
method
};
},
/* once http.get returns a response, build it and
* resolve or reject the Promise */
_onResponse(response, resolve, reject) {
const hasResponseFailed = response.status >= 400;
var responseBody = '';
if (hasResponseFailed) {
reject(`Request to ${response.url} failed with HTTP ${response.status}`);
}
/* the response stream's (an instance of Stream) current data. See:
* https://nodejs.org/api/stream.html#stream_event_data */
response.on('data', chunk => responseBody += chunk.toString());
// once all the data has been read, resolve the Promise
response.on('end', () => resolve(responseBody));
}
};
EDIT: I only just realised you're new to Promises. Here's an example of how to use this wrapper:
'use strict';
const httpService = require('./httpService'); // the above wrapper
// get one URL
httpService.get('https://ron-swanson-quotes.herokuapp.com/v2/quotes').then(function gotData(data) {
console.log(data);
});
// get multiple URLs
const urls = [
'https://ron-swanson-quotes.herokuapp.com/v2/quotes',
'http://api.icndb.com/jokes/random'
];
/* map the URLs to Promises. This will actually start the
* requests, but Promise.prototype.then is always called,
* even if the operation has resolved */
const promises = urls.map(url => httpService.get(url));
Promise.all(promises).then(function gotData(responses) {
/* responses is an array containing the result of each
* Promise. This is ordered by the order of the URLs in the
* urls array */
const swansonQuote = responses[0];
const chuckNorrisQuote = responses[1];
console.log(swansonQuote);
console.log(chuckNorrisQuote);
});

Using Promise.all is the most efficient solution for this. You could also use async/await like below to solve this.
const http = require('http');
const bl = require('bl');
async function httpGet(url) {
return new Promise((resolve, reject) => {
http.get(url, response => {
response.setEncoding('utf8');
response.pipe(bl((err, data) => {
if (err) {
reject(err);
}
resolve(data.toString());
}));
});
});
}
async function main() {
const data1 = await httpGet(process.argv[2]);
const data2 = await httpGet(process.argv[3]);
const data3 = await httpGet(process.argv[4]);
console.log(data1);
console.log(data2);
console.log(data3);
}
main();

I don't think this exercise was meant to be solved with promises. I found my old exercice folder, this is how I did it without promises or extra libraries:
var http = require('http');
var urls = process.argv.slice(2);
// counts the number of requests done
var done = 0;
// stores the requests result
var result = [];
// this will be called by each http.get and they will provide their index
function callback(index, data) {
result[index] = data;
done++;
// all requests are done, log everything
if (done == urls.length) {
result.forEach(console.log);
}
}
function processUrl(url, index) {
var finalData = '';
http.get(url, function(response) {
response.setEncoding('utf8');
response.on('data', function(data) {
finalData += data;
});
response.on('error', console.error);
response.on('end', function() {
// console.log(finalData);
callback(index, finalData);
})
});
}
urls.forEach(processUrl);
Don't worry, you'll have enough promises to play with in the promise-it-wont-hurt workshop.

A bit late to the party here :)
Unfortunately none of the answers here uses the builtin util module in node.
Here is how to promisify http.get using util module and it is working correctly with typescript:
import util from "util";
const httpGetPromisified = util.promisify(
(url: string, cb: (err: any, result: IncomingMessage) => void) =>
http.get(url, (res) => cb(null, res))
);
// with promise.then
httpGetPromisified("http://www.google.com").then((res) => {
// res here has type http.IncomingMessage
console.log(res.statusCode);
});
// with async/await
const res = await httpGetPromisified("http://www.google.com");
console.log(res.statusCode);

Here's my solution after going through this thread:
var http = require('http');
var bl = require('bl')
promises = [
promiseLoad(process.argv[2]),
promiseLoad(process.argv[3]),
promiseLoad(process.argv[4])
];
Promise.all(promises).then(function(res) {
for(i=0; i<promises.length; i++) {
console.log(res[i]);
}
});
function promiseLoad(url) {
var body = '';
return new Promise(function(resolve, reject) {
http.get(url, function (response) {
response.setEncoding('utf8');
response.pipe(bl(function (err, data) {
resolve(data.toString())
}))
})
});
}
Here's the official solution in case you want to compare notes:
var http = require('http')
var bl = require('bl')
var results = []
var count = 0
function printResults () {
for (var i = 0; i < 3; i++) {
console.log(results[i])
}
}
function httpGet (index) {
http.get(process.argv[2 + index], function (response) {
response.pipe(bl(function (err, data) {
if (err) {
return console.error(err)
}
results[index] = data.toString()
count++
if (count === 3) {
printResults()
}
}))
})
}
for (var i = 0; i < 3; i++) {
httpGet(i)
}

const http = require('http');
const urls = process.argv.slice(2);
let callCount = 0;
const cb = (res) => {
res.setEncoding('utf8');
let rawData = '';
res.on('data', (chunk) => {
rawData += chunk.toString();
});
res.on('end', () => {
callCount += 1;
console.log(rawData);
if (callCount < urls.length) {
getData(urls[callCount]);
}
});
res.on('error', (error) => {
console.log(error);
});
};
const getData = (url) => {
http.get(url, cb);
};
getData(urls[callCount]);

Here's how I did it:
async myFunc = function {
let url = 'http://your.data/file';
let promise = new Promise((resolve, reject) => {
var data = '';
https.get(url, res => {
res.on('data', chunk => { data += chunk })
res.on('end', () => {
resolve(data);
})
})
});
let result = await promise; // wait until the promise resolves
doStuffWithResult(result);
};

One of the method is by using 'Q' library.
First create function that will hit URL and return promise
var Q = require('q);
function getIt(item){
return http.get(item,function(response){
return Q.resolve(response); // Return response
OR
return Q.resolve(error); // Return error
})
})
}
var urls = ['url1','url2','url3']; // list of urls
Q.spread(urls.map(getIt))
.then(function(res1,res2,res3){
// res1 is response for url1 and on
//Once all calls are finished you will get results here
});

Related

JavaScript Dynamic Promises

I am trying to understand how promises work in JS by playing with swapi.dev. I would like to create a dynamic chain of promises (not using async/await) but it does not provide me with any result. In particular, the idea behind is to get all names of the given person (for instance Luke Skywalker) and dump them into the console.
Could anyone help me? What am I missing?
Thanks in advance.
"use strict";
const request = require("request-promise");
const BASE_URL = "http://swapi.dev/api";
var currentPromise = Promise.resolve();
callApiPromise(`${BASE_URL}/people/1`).then((data) => {
console.log("Getting vehicles' URLs");
const vehicles_URL = data["vehicles"];
console.log("Starting looping through URLs");
for (let i = 0; i < vehicles_URL.length; i++) {
console.log(`i=${i}, vehicle_URL=${vehicles_URL[i]}`);
currentPromise = currentPromise.then(function () {
console.log(".. getting vehicle name");
return getVehicleName[vehicles_URL[i]];
});
}
});
function getVehicleName(url) {
callApiPromise(url).then((vehicle_data) => {
var arrVehicleData = new Array();
arrVehicleData.push(vehicle_data);
console.log(arrVehicleData.map((vehicle) => vehicle.name));
});
}
function callApiPromise(url) {
return new Promise((resolve, reject) => {
callApi(url, (err, data) => {
if (err) {
reject(err);
return;
}
resolve(data);
});
});
}
function callApi(url, callback) {
request
.get(url)
.then((response) => {
const json = JSON.parse(response);
callback(null, json);
})
.catch((err) => {
callback(err, null);
});
}
Some issues:
A missing return statement in getVehicleName
A syntax issue in getVehicleName[vehicles_URL[i]] (should be parentheses)
As the promises for getting the vehicle names are independent, you would not chain them, but use Promise.all
arrVehicleData will always only have one element. There is no reason for an array there where it is used.
You are also taking the wrong approach in using request.get. The bottom function turns that API from a Promise-API to a callback API, only to do the reverse (from callback to promise) in the function just above it. You should just skip the callback layer and stick to promises:
"use strict";
const request = require("request-promise");
const BASE_URL = "http://swapi.dev/api";
getJson(`${BASE_URL}/people/1`).then(data => {
return Promise.all(data.vehicles.map(getVehicleName));
}).then(vehicleNames => {
console.log(vehicleNames);
// Continue here...
});
function getVehicleName(url) {
return getJson(url).then(vehicle => vehicle.name);
}
function getJson(url, callback) {
return request.get(url).then(JSON.parse);
}
Finally, you should not use request-promise anymore since the request module, on which request-promise depends, has been deprecated
The getVehicleName doesn't return a promise. Instead it invokes a promise that by the time it will be resolved, the for loop invoking it will already be removed from the call stack.
This is a sample of promise chaining:
const promise = new Promise(resolve => resolve(1))
const promise1 = Promise.resolve(2)
const methodReturnPromise = () => new Promise(resolve => resolve(3))
promise.then(firstPromiseData => {
// do something with firstPromiseData
console.log(firstPromiseData)
return promise1
}).then(secondPromiseData => {
// do something with secondPromiseData
console.log(secondPromiseData)
return methodReturnPromise()
}).then(thirdPromiseData => {
// do something with thirdPromiseData
console.log(thirdPromiseData)
})

How to make HTTP request with promises and retries in Node.js

I am trying to write a few wrappers around Node HTTP/S module requests, without using axios. node-fetch or any other 3rd party module.
For example, I want to have functions sendGet, sendPost, sendJSON, sendFile etc. In ideal case, these functions will be implementing core functionmakeRequest, just with different parameters.
I want each wrapper to return a promise, so the caller can do anything with the result.
I also want the wrapper to have an argument, how many times will be request retried in case of failure.
So idea is something like this. So far I am able to make a wrapper and pass promise. But I am unable to add ability to retry on failure. It should be (in ideal scenario), part of makeRequest function, but I was unable to to do so, when combined with promises. Thank you for your ideas
// intended usage of wrapper
sendGet('http://example.com', 3).then().catch()
// wrapper applies makeRequest fnc with various arguments
const sendGet = (url, retries) => {
return makeRequest('GET', url, retries)
}
const sendPost = (url, retries) => {
return makeRequest('POST', url, retries)
}
// core function
const makeRequest = async (method, url, retries = 0) => {
// returns reject on bad status
// returns resolve with body on successful request
return new Promise((resolve, reject) => {
const options = {/*method, hostname, etc */};
const request = http.request(options, (response) => {
let chunks = [];
if (response.statusCode < 200 || response.statusCode >= 300) {
return reject('bad status code')
}
// collect data
response.on('data', (chunk => {
chunks.push(chunk)
}))
// resolve on end of request
response.on('end', () => {
let body = Buffer.concat(chunks).toString();
return resolve(body)
})
})
request.end();
})
}
Try this, the original function now is called tryRequest and outside there is the for loop to do the retries
// core function
const makeRequest = async (method, url, retries = 0) => {
const tryRequest = async () => {
// returns reject on bad status
// returns resolve with body on successful request
return new Promise((resolve, reject) => {
const options = {method, };
const request = http.request(url, options, (response) => {
let chunks = [];
if (response.statusCode < 200 || response.statusCode >= 300) {
return reject('bad status code')
}
// collect data
response.on('data', (chunk => {
chunks.push(chunk)
}))
// resolve on end of request
response.on('end', () => {
let body = Buffer.concat(chunks).toString();
return resolve(body)
})
})
// reject on error of request (Service down)
request.on('error', function (error) {
reject(error);
})
request.end();
})
}
for (let i=1; i<=retries; i++) {
try {
console.log('Try No.', i);
url = url.substring(0, url.length - 1); // TODO To test, delete after it
return await tryRequest();
} catch(error) {
if (i < retries) continue;
throw error;
}
}
}
Test
await sendGet('http://example.com/abc', 3); // Will work at the 3th try retry
await sendGet('http://example.xyz/abc', 3); // Will fail server not found
You can use a custom promise & axios or any other promise-based request:
(Live Demo)
import { CPromise } from "c-promise2";
import cpAxios from "cp-axios";
const url =
"https://run.mocky.io/v3/7b038025-fc5f-4564-90eb-4373f0721822?mocky-delay=2s";
(async()=>{
const response= await CPromise.retry(() => cpAxios(url).timeout(5000));
})();
More complex:
import { CPromise } from "c-promise2";
import cpAxios from "cp-axios";
const url =
"https://run.mocky.io/v3/7b038025-fc5f-4564-90eb-4373f0721822?mocky-delay=2s";
const promise = CPromise.retry(
(attempt) => {
console.log(`Attempt [${attempt}]`);
return cpAxios(url).timeout(attempt * 1000 + 500);
},
{ retries: 3, delay: (attempt) => attempt * 1000 }
).then(
(response) => console.log(`Response: ${JSON.stringify(response.data)}`),
(err) => console.warn(`Fail: ${err}`)
);
// promise.pause()
// promise.resume()
// promise.cancel()

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.

How to add server-side delay to Javascript for loop?

I'm fiddling around with using Node.js to scrape data from an e-commerce site. I use Request to retrieve the DOM of the page and Cheerio to do server-side DOM selection.
const cheerio = require('cheerio');
const request = require('request');
// takes a URL, scrapes the page, and returns an object with the data
let scrapePage = (url) => {
return new Promise((resolve, reject) => {
request(url, (error, resp, body) => {
if(error){
reject(error);
};
let $ = cheerio.load(body);
let $url = url;
let $price = $('#rt-mainbody > div > div.details > div.Data > div:nth-child(4) > div.description').text();
let obj = {
url: $url,
price: $price
}
resolve(obj);
});
});
};
// Runs scrapePage in a loop
// There is a variable called arrayOfURLs defined elsewhere that contains 100s of URLs
for( let i = 0; i < arrayOfURLs.length; i++){
scrapePage(arrayOfURLs[i])
.then((obj) => {
//write to a file
})
.catch((error) => {
})
};
The problem is that the server that I send requests to sometimes sends back blank data, I'm assuming because I'm sending too many requests without any kind of pause. Due to the async nature of JS I'm having a hard time figuring out how to add an effective delay between each iteration of the loop. It's not enough to just add a setTimeOut in a synchronous fashion because setTimeOut itself is async, and I'm running this on the server so there's no Window object.
EDIT
The code above is a simplified version of what I'm working on. The entire code is this:
app.js
const fs = require('fs');
const path = 'urls.txt';
const path2 = 'results.txt';
const scraper = require('./scraper');
let scrapePage = (url) => {
scraper.scrapePage(url)
.then((obj) => {
// console.log('obj from the scraper with Promises was received');
// console.log(obj);
// console.log('writing obj to a file');
fs.appendFile(path2, JSON.stringify(obj) + ', ', (error) => {
if(error){
console.log(error);
} else {
// console.log('Successfully wrote to ' + path2);
}
})
})
.catch((error) => {
console.log('There was an error scraping obj: ');
console.log(error);
})
}
fs.readFile(path, 'utf8', (err, data) => {
if (err){
throw err;
};
var urlArray = JSON.parse(data);
// this returns an Unexpected Identifier error
// const results = await Promise.all(urlArray.map(scrapePage));
// this returns an Unexpected Token Function error
// async function scrapePages(){
// const results = await Promise.all(urlArray.map(scrapePage));
// };
});
scraper.js
const request = require('request');
const cheerio = require('cheerio');
exports.scrapePage = (url) => {
return new Promise((resolve, reject) => {
request(url, (error, resp, body) => {
if(error){
reject(error);
};
let $ = cheerio.load(body);
let $url = url;
let $price = $('#rt-mainbody > div > div.details > div.itemData > div:nth-child(4) > div.description').text();
let obj = {
url: $url,
price: $price
}
resolve(obj);
})
})
}
Looks to me like you aren't waiting for your promises to resolve before you send the server response. You could completely eliminate the for loop using using async / await e.g.
const results = await Promise.all(arrayOfURLs.map(scrapePage));
If you want to have no more than x amount of active connections you could use throttle. Or if you want no more than x amount per second you could use throttlePeriod.
Using Promise.all will never call your resolve handler if only one request fails so you could catch any errors and return a Fail object
const Fail = function(details){this.details=details;};
const max10 = throttle(10)(scrapePage);//max 10 active connections
//const fivePerSecond = throttlePeriod(2,1000)(scrapePage); //start no more than 2 per second
Promise.all(
arrayOfURLs.map(
url =>
max10(url)
.catch(err=>new Fail([err,url]))
)
)
.then(
results =>{
successes =
results.filter(
result=>(result&&result.constructor)!==Fail
);
failed =
results.filter(
result=>(result&&result.constructor)===Fail
)
}
);
const cheerio = require('cheerio');
const request = require('request');
let scrapePage = (url) => {
return new Promise((resolve, reject) => {
request(url, (error, resp, body) => {
if(error){
reject(error);
return;
};
if(!body) {
reject('Empty Body');
return;
}
let $ = cheerio.load(body);
let $url = url;
let $price = $('#rt-mainbody > div > div.details > div.Data > div:nth-child(4) > div.description').text();
let obj = {
url: $url,
price: $price
}
resolve(obj);
});
});
};
function processUrl(url){
scrapePage(url)
.then((obj) => {
//write to a file
if(i < arrayOfURLs.length)
processUrl(arrayOfURLs.pop())
})
.catch((error) => {
arrayOfURLs.unshift(url);
if(i < arrayOfURLs.length) // put this in finally block
processUrl(arrayOfURLs.pop())
})
};
processUrl(arrayOfURLs.pop());
Here we can use arrayOfUrls arrays as queue and if we received an error or blank page, we push this URL in array again. in that way we can process every URL in a synchronous fashion.

Using Promise.all

Firstly apologies if this is a simple problem to solve but I am using node-fetch and the concept of Promises for the first time. I am calling an api endpoint which returns paginated data so i get multiple links for further data.
I am handling this by putting all the links into an array and then I want to call each endpoint in the array and just print out the data to the console for now
So my first call is
var urlArray = [];
fetch(`${BASE_URL}/leagues?api_token=${AUTH_TOKEN}`, { headers: headers })
.then(function(response){
return response.json(); // pass the data as promise to next then block
})
.then(function(json){
// Collect Paginated Results
var number_of_pages = parseInt(json.meta['pagination']['total_pages']);
for (i = 2; i < number_of_pages + 1; i++) {
urlArray.push(`${BASE_URL}?page=${i}&api_token=${AUTH_TOKEN}`)
}
})
.catch(function(error) {
console.log(error);
});
So once this done i have an array of urls i need to hit sequentially, could anyone give me some pointers please on how to then setup a promise to hit each one? or can i have something where is do it in my for loop?
Thanks
sorry if this is wrong!
At the beginning, put:
var promise_array = [];
in the for loop, replace with
for (i = 2; i < number_of_pages + 1; i++) {
var url = `${BASE_URL}?page=${i}&api_token=${AUTH_TOKEN}`;
urlArray.push(url);
promise_array.push(fetch(url));
}
At the end of the function put
Promise.all(promise_array).then(all_responses => {
// .. pluck json, then continue ...
});
You can achieve this by:
fetch(`${BASE_URL}/leagues?api_token=${AUTH_TOKEN}`, { headers: headers }).then(response => {
var json = response.json();
var numberOfPages = parseInt(json.meta['pagination']['total_pages']);
var urlArray = [];
for (i = 2; i < numberOfPages + 1; i++) {
urlArray.push(`${BASE_URL}?page=${i}&api_token=${AUTH_TOKEN}`)
}
var promises = urlArray.map(url => getSomethingByUrl(url));
return Promise.all(promises);
}).then(results => {
console.log(results);
});
You can use Array.prototype.reduce to create Promise chain so they will be executed one after another
urls.reduce((prev, item) => {
return prev.then(() => {
return someAction(item);
})
}, Promise.resolve()).then(() => {
console.log('All done');
}).catch((err) => {
console.log(err);
});
Edit:
As mentioned by Bergi, value from someAction should be returned in case it's asynchronous (return Promise). If someAction is asynchronous it must return Promise.
"use strict";
function someAction(i) {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log(i);
resolve(i);
}, i*1000);
});
}
const urls = [1,2,3,4,5];
urls.reduce((prev, item) => {
return prev.then(() => {
return someAction(item);
})
}, Promise.resolve()).then(() => {
console.log('All done');
}).catch((err) => {
console.log(err);
});

Categories