在Promise中不使用拒绝可以吗?

时间:2018-10-15 18:33:18

标签: javascript promise

构造一个永不拒绝的承诺可以吗?我的意思是说这是某种反模式还是可以接受的?让我用一个例子来说明。我有一个ModifyURL类,它由许多方法组成,每个方法都使用URI字符串数组执行某些操作并返回Promise。实现的一部分看起来像这样。

class ModifyURL {
    constructor() {

    }
    /**
     * Remove empty and invalid urls
     * @param {object} object containing arrays of links
     *
     * @return {object} object containing arrays of valid links
     */
    removeInvalid(data) {
        return new Promise((resolve,reject)=>{
            for (let key in data) {
                data[key] = data[key].filter( function(item) {
                    return !(item == '#' || !item || item == ' ');
                });
            }
            resolve(data)
        });
    }

    /**
     * Remove duplicates
     * @param {object} object containing arrays of links
     *
     * @return {object} object containing arrays of unique links
     */
    removeDuplicates(data) {
        return new Promise((resolve,reject)=>{
            for (let key in data) {
                data[key] = data[key].filter(function (item, pos) {
                    return data[key].indexOf(item) == pos;
                })
            }
            resolve(data)
        });
    }
    /**
     * Add full hostname to relative urls.
     * @param {object}  object containing arrays of links
     * @param {string} hostname to be added if link is relative
     *
     * @return  {object} object containing arrays of absolute links
     */
    fixRelativeLinks(data,hostname) {
        if(typeof data === 'object'){
            return new Promise((resolve,reject)=>{
                for (let key in data) {
                    data[key].forEach((v, i) => {
                        if(data[key][i]){
                            data[key][i] = URL.resolve(hostname, data[key][i])
                        }
                    })
                }
                resolve(data)
            })
        }
    }
}

稍后我将这些Promises链接起来,并且效果很好。

                            modifyURL.removeInvalid(data).then(res=>{
                                return res
                            })
                            .then(()=>{
                                return modifyURL.fixRelativeLinks(data, res.request.href)
                            })
                            .then(modifyURL.removeDuplicates).then(res=>{
                                onSuccess(res)
                            }).catch(err=>{console.log(err)})

您注意到我不使用拒绝,感觉有点奇怪。原因是最后我需要接收一些数据。即使链中的某些 Promise 不能完成其任务,我仍然需要最终用我的URI字符串数组解决。这就是为什么我不拒绝的原因,因为它破坏了我的承诺链。但是如果没有拒绝,我就无法正确地跟踪错误。处理此类任务的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

  

构造一个永不拒绝的承诺可以吗?

是的,没关系。如果操作中没有可能发生的错误,那么仅应诺就可以解决。

  

我的意思是说这是某种反模式还是可以接受的?

有一个永不拒绝的承诺是完全可以接受的(假设有一些可以解决的代码路径)。例如,您可能编写了一个函数,该函数可以在特定的延迟后解析承诺,例如:

function delay(t, v) {
    return new Promise(resolve => {
        setTimeout(resolve, t, v);
    });
}
  

我有一个ModifyURL类,该类包含许多方法,每个方法都使用URI字符串数组执行某些操作并返回Promise。实现的一部分看起来像这样。

这些都是同步功能。它们不需要包装在诺言中,也不应该包装在诺言中。承诺用于跟踪异步操作。当它们与纯同步代码一起使用时,它们只会创建比必要时复杂的代码。

虽然可以用promise包装同步操作(如您所愿),但我会称其为反模式,因为它使代码比仅使用一个接一个地调用多个函数的普通同步编码模式复杂得多或者如果它们都对相同的数据进行操作,则将这些函数作为对象的所有方法,然后一个接一个地调用它们。

  

您注意到我不使用拒绝,感觉有点奇怪。这样做的原因是,最后我需要接收一些数据。

首先,您在此处将诺言与同步代码滥用。但是,通常使用异步代码,您的代码就可以确定发生错误时会发生什么。您可以让拒绝传播并停止链,也可以在本地捕获拒绝并将其更改为希望链继续的任何内容,并且链不会知道发生了任何错误。这取决于您和您的代码。您完全可以控制。

  

即使链中的某些Promise不能完成其任务,我也需要最终使用我的URI字符串数组来解决。

这只是具有适当的本地错误处理,因此您可以在本地捕获和处理任何错误,以便您可以继续处理其余数据并返回已成功处理的数据。这与使用try/catch和同步代码在本地捕获错误,因此在概念上没有什么不同,因此您可以捕获它们,但是适当地处理它们,然后继续进行其余的工作。

  

这就是为什么我不拒绝,因为它打破了我的Promise链。但是如果没有拒绝,我将失去正确跟踪错误的能力。处理此类任务的正确方法是什么?

对此并没有真正的通用答案,因为它实际上取决于特定的应用程序,它在做什么以及您希望如何将结果和错误进行回传。有时您会在第一个错误时中止链条(快速失败)。有时,您会跳过错误而仅返回成功的结果。有时您返回结果数组和错误数组。有时,您返回一个既包含结果又包含错误的数组,并以数据格式提供一些手段来知道哪个是错误的,哪个是成功的结果。而且,您可以想出许多其他方式来同时传达结果和错误。