【问题标题】:Two rejects in One Promise一个 Promise 中的两个拒绝
【发布时间】:2019-06-21 16:45:54
【问题描述】:

我是 JavaScript 新手。我不知道哪里可以在一个承诺中使用两个拒绝;谁能告诉我在一个承诺中有两个拒绝是不好的做法?如果是,可选的解决方案是什么?

这是我的代码

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");
                        }       
                    })
                });
            }

【问题讨论】:

  • 只有第一个拒绝才会做任何事情。一旦 Promise 被拒绝,它就不能被拒绝或再次解决(再次调用 rejectresolve 是无害的,但什么也不做);它永久处于拒绝状态。您可能应该提前返回:return reject(err);,以便在您拒绝后其余代码不会在函数中运行。

标签: javascript node.js ecmascript-6 es6-promise


【解决方案1】:

你可以在你的 Promise 回调中有多个调用 reject(err) 的地方。只有第一个执行的才重要。对 reject() 的后续调用将被忽略,因为一旦设置了 Promise 状态,就无法通过进一步调用 reject()resolve() 来更改它。

通常最好的做法是在您拒绝时使用return 结束您的函数执行或使用else 语句,因为继续执行其他无法解决或拒绝的事情通常是没有意义的,并且在某些情况下有害的情况。

因此,在您的具体情况下,您可以像这样添加return

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");
            }
        })
    });
}

或者,您可以添加一个 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");
                }
            }
        })
    });
}

【讨论】:

    【解决方案2】:

    是的,您可以在承诺中使用任意数量的reject。只是拒绝需要在不同的流程上。意味着调用一个reject 又一个reject 将不起作用。因为不会一个接一个地调用resolve resolve

    为了确保其他代码不运行,最好在reject 之前添加return

    例如:

    const checkIfRightPermission = new Promise((res, rej) =>{
        //let's say we are doing an http request.
        request.get('/getPermission?id=someid', function(err, res, body){
            if(err){
                //the request itself couldn't be completed SO
                return rej();
            }else{
                if(sufficientPermission(body)){
    
                }else{
                    //again
                    return rej()
                }
            }
        })
    
    });
    

    【讨论】:

      【解决方案3】:

      您应该尝试在 if else 块中保留每个解析和拒绝。

      if (condition1) {
        resolve(true);
      } else if (condition2) {
        reject(false);
      } else {
        reject(false);
      }
      

      例如,如果您要这样做:

      if (condition1) {
        resolve(true);
      }
      reject(false);
      

      你应该改为:

      if (condition1) {
        resolve(true);
        return;
      }
      reject(false);
      

      【讨论】:

        【解决方案4】:

        使用多个rejects没有问题,这完全取决于您的逻辑,并且以这种方式使用。

        我建议您更改的唯一一件事是 Promise 中的 try/catch 块,当您抛出异常时,下一个 promise.catch 将处理它。

        看看:

        https://medium.com/datafire-io/es6-promises-patterns-and-anti-patterns-bbb21a5d0918

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-11-22
          • 1970-01-01
          • 2016-11-10
          • 2017-01-04
          • 2021-12-10
          相关资源
          最近更新 更多