0

consider the code given below. Here I am reading four files three of which is json and one is html. The function readJson reads file one by one and returns promise either resoved or rejected. So my problem is if first three files are read without any error except the last one index.html, then the first three files should be logged except the last one. But this not so the program does not print any of the file. why?

var pages = [
        "a.json",
        "b.json",
        "c.json",
        "index.html"
    ];
var fs = require('fs');

function readJson(page){
    console.log("this file name is:",page);
    return new Promise(function(resolve,reject){
        fs.readFile("./"+page,"utf8",function(err,res){
            if(err){
                reject(err);
            }else{
                try {
                    resolve(JSON.parse(res));
                } catch (ex) {
                    reject(ex);
                }
            }
        });
    });
}

function readAll(pages){
    return Promise.all(pages.map(readJson));
}

readAll(pages).then(function(allPages){
    allPages.forEach(function(page){
        console.log("++++++++++++++++++++++++++++++++++++++++++");
        console.log(page);
    });
})
.catch(function(err){
    console.log("-----------------------------------------------");
    console.log(err);
})
nurulnabi
  • 459
  • 3
  • 11
  • 1
    because that's how `Promise.all` rolls ... one rejection, will cause `Promise.all` to reject - of course, you could `resolve('')` instead of rejecting in `readJson` – Jaromanda X Feb 28 '17 at 05:24
  • You can use logic within `readJson` to call `JSON.parse()` or not or pass `res` to `resolve()`. – guest271314 Feb 28 '17 at 05:28
  • you guys mean to say if one rejection or error happens all of the promises get rejected whether they are fulfilled or not. then what is the benefits of using promise.all, anyway I can achieve this by chaining the promises. – nurulnabi Feb 28 '17 at 05:39
  • Yes. That is how `Promise.all()` performs. You could alternatively call the functions in sequence, without using `Promise.all()`, or handle the rejection at `.catch()` and return a resolved `Promise`. – guest271314 Feb 28 '17 at 05:41
  • kindly read my updated comment – nurulnabi Feb 28 '17 at 05:41
  • If I can achieve what Promise.all does with chaining then what is benefit of Promise.all over sequencing the promises. – nurulnabi Feb 28 '17 at 05:43
  • One possible "benefit" would be a case where all `Promise`s passed to `Promise.all()` are expected to be resolved. Yes, you could chain using `.then()`. It depends on how you decide to handle the process. Given `javascript` at Question, you can adjust logic within `readJson` to handle `res` being `html`. Is Question about `Promise.all()` specification or how to adjust `javascript` at Question to return expected result? – guest271314 Feb 28 '17 at 05:44
  • 1
    `if one rejection or error happens all of the promises get rejected` - no ... the single promise returned by `Promise.all` either fulfills as an array of "fulfilled" values **or** the rejection reason for the **first** rejected promise of the input array – Jaromanda X Feb 28 '17 at 05:46
  • @nurulnabi See also [How does promise.all work?](http://stackoverflow.com/questions/31299231/how-does-promise-all-work/), [promise.all inside a forEach loop — everything firing at once](http://stackoverflow.com/questions/37089515/promise-all-inside-a-foreach-loop-everything-firing-at-once), [Jquery Ajax prevent fail in a deferred sequential loop](http://stackoverflow.com/questions/28131082/jquery-ajax-prevent-fail-in-a-deferred-sequential-loop/). Though left unadjusted, the issue remains as to `JSON.parse()` being passed `html`. – guest271314 Feb 28 '17 at 06:11

1 Answers1

0

Promise.all is designed to fail-fast - i.e when even one of the promises rejects, all of them are rejected. If you still need the response (resolution or error), you could use something like this —

function readAll(pages) {
    return Promise.all(pages.map(readJson).map(p => p.catch(e => new Error(e))))
        .then(results => results);
}

This returns an array of successful resolutions or Error objects, as catch is never returned. You can then figure out if some exception occurred using some logic like this —

readAll(pages).then(function (allPages) {
    allPages.forEach(function (page) {
        if (page instanceof Error) {
            console.log("-----------------------------------------------");
            console.log(page);
        } else {
            console.log("++++++++++++++++++++++++++++++++++++++++++");
            console.log(page);
        }
    });
})
GPX
  • 3,506
  • 10
  • 52
  • 69