Search code examples
javascriptnode.jsecmascript-6es6-promise

Two rejects in One Promise


I am new to JavaScript. I don't know where I can use two rejects inside one promise; can anyone tell me that it's bad practice to have two rejects in one promise? If yes, what will be the optional solution?

Here is my code

async handler(ctx) {
                /*
                 * sheet_to_json method converts excel file to JSON format
                */
                let { s3Url, header } = ctx.params;
                return new Promise((resolve, reject) => {
                    request({method: 'GET',  uri: s3Url,encoding: null}, async function(err, res, data) {
                        if(err || res.statusCode !== 200) reject(err);
                        try{
                            const workbook = XLSX.read(data, {type:'buffer'});
                            const sheet_name_list = workbook.SheetNames;
                            let result = await XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]], {header});
                            resolve(result);
                        }
                        catch(error){
                            reject("Invalid File Cointaint");
                        }       
                    })
                });
            }

Solution

  • You can have multiple places that you call reject(err) inside your promise callback. Only the first one to execute will matter. Subsequent calls to reject() are ignored because once the Promise state is set, it cannot be changed by further calls to reject() or resolve().

    It is generally good practice to end your function execution with a return or to use an else statement when you reject since continuing to do other stuff that isn't going to resolve or reject is usually meaningless and in some cases harmful.

    So, in your specific case, you can either add a return like this:

    async handler(ctx) {
        /*
         * sheet_to_json method converts excel file to JSON format
         */
        let {s3Url,header} = ctx.params;
        return new Promise((resolve, reject) => {
            request({method: 'GET', uri: s3Url, encoding: null}, async function(err, res, data) {
                if (err || res.statusCode !== 200) return reject(err); // <==== return added here
                try {
                    const workbook = XLSX.read(data, {type: 'buffer'});
                    const sheet_name_list = workbook.SheetNames;
                    let result = await XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]], {header});
                    resolve(result);
                } catch (error) {
                    reject("Invalid File Cointaint");
                }
            })
        });
    }
    

    Or, you can add an else:

    async handler(ctx) {
        /*
         * sheet_to_json method converts excel file to JSON format
         */
        let {s3Url, header} = ctx.params;
        return new Promise((resolve, reject) => {
            request({method: 'GET', uri: s3Url, encoding: null}, async function(err, res, data) {
                if (err || res.statusCode !== 200) {
                    reject(err);
                } else {           // <======== else added here
                    try {
                        const workbook = XLSX.read(data, {type: 'buffer'});
                        const sheet_name_list = workbook.SheetNames;
                        let result = await XLSX.utils.sheet_to_json(workbook.Sheets[sheet_name_list[0]], {header});
                        resolve(result);
                    } catch (error) {
                        reject("Invalid File Cointaint");
                    }
                }
            })
        });
    }