在Promise解析器中捕获错误

时间:2016-12-21 03:31:15

标签: javascript promise

我无法捕获Resolve promise中发生的异常/错误。 有人可以解释是否有办法捕捉到这个错误:

createAsync = function() {
    var resolve, reject,
    promise = new Promise(function(res, rej) {
        resolve = res;
        reject = rej;
    });
    promise.resolve = resolve;
    promise.reject = reject;
    return promise;
};

promise = createAsync()
promise.then(function myresolver(){
    throw Error('wow')
})


// Catching the error here
try {
  promise.resolve()
} catch(err) {
  console.log( 'GOTCHA!!', err );
}

编辑:

让我更好地解释一下,我正在尝试创建一个API,用户只能访问promise promise / reject部分:

// This is my API user does not have access to this part
promise = createAsync()
promise
.then(function(fun) {
    if (typeof fun != 'function')
        throw Error('You must resolve a function as argument')
}).catch(function(err){
    // Some internal api tasks...
    return Promise.reject(err)
})

现在我想给他的解决方案,但不起作用:

// Here is where the user can resolve the promise.
// But must be able to catch the error
promise.catch(function(err){
    console.log("GOTCHA", err)
})
promise.resolve('This must be a function but is a string');

有什么想法吗?

更多信息: 是的是常用的反模式。这是一个远程过程调用API,因此用户必须能够拒绝或解决。并且调用是异步的,因此最好的方法是使用promises。我不会说这是一个反模式。实际上是唯一的模式。 (我不能使用Async / Await)

3 个答案:

答案 0 :(得分:3)

  

让我更好地解释一下,我尝试创建一个API,用户只能访问promise resolve / reject部分。   现在我想给他的解决方案不起作用。   有什么想法吗?

不要将所有内容都放在最初的promise对象上。听起来你真正需要向用户公开的是a)一种解决方法(包括拒绝)和b)一种获得结果(承诺)的方法。所以你需要做的就是给他一个功能:

function createAsync() {
    var resolve;
    var promise = new Promise(function(r) { resolve = r; })
    .then(function(fun) {
        if (typeof fun != 'function')
            throw Error('You must resolve a function as argument')
    }).catch(function(err){
       // Some internal api tasks...
       throw err;
    });
    return function(value) {
        resolve(value);
        return promise;
    };
}

他会像

一样使用它
var start = createAsync();
// possibly later
start('This must be a function but is a string').catch(function(err){
    console.log("GOTCHA", err)
});
// or
start(Promise.reject(new Error('doomed to fail'))).catch(…);

但实际上这种模式仍然令人费解,而且过于复杂。只需给你的createAsync函数一个参数(如果用户需要延迟传递fun,可能会收到一个承诺)并完成它:

function createAsync(valu) {
    return Promise.resolve(val).then(function(fun) {
        if (typeof fun != 'function')
            throw Error('You must resolve a function as argument')
    }).catch(function(err){
       // Some internal api tasks...
       throw err;
    });
}

createAsync('This must be a function but is a string').catch(function(err) {
    console.log("GOTCHA", err)
});
// or
createAsync(new Promise(function(resolve) {
    // later
    resolve('This must be a function but is a string');
})).catch(function(err) {
    console.log("GOTCHA", err)
});

答案 1 :(得分:2)

  

警告:正如@torazaburo指出“导出”提供给执行程序的解析和拒绝函数(传递给promise构造函数的函数),在您的情况下通过使用其他属性污染promise对象,是反模式。 promise构造函数的设计的全部要点是在执行程序中隔离解析和拒绝。您的方法允许任何碰巧获得您的承诺对象的随机人员解决或拒绝它,这几乎肯定不是好的程序设计。

考虑到这一警告,您对promise.resolve()的呼吁不会拒绝承诺......您的promise.then ... throw将“拒绝”承诺(由.then返回的承诺)而不是承诺promise

重写您的代码如下:

promise = createAsync()
promise // the call to promise.resolve will resolve THIS promise, so .then will execute
.then(function myresolver(){
    throw Error('wow')
}) // .then returns a NEW promise, in this case rejected with Error('wow')
.catch(function(e) {
    console.log("GOTCHA", e)
});

promise.resolve()

您将在控制台中看到预期的 GOTCHA

答案 2 :(得分:1)

Jaromanda's answer已经解释过必须使用拒绝处理程序或catch来使用promises处理异步错误。

另外,请务必阅读 torazaburo 的评论,解释为什么您的方法是反模式。

如果你真的必须使用这种方法,并且出于某种原因也需要try/catch,那么ES7会通过async functions

为您提供一种方法

(async function f() {
  const createAsync = function() {
    var resolve, reject,
      promise = new Promise(function(res, rej) {
        resolve = res;
        reject = rej;
      });
    promise.resolve = resolve;
    promise.reject = reject;
    return promise;
  };

  const promise = createAsync();
  promise.resolve();

  // Catching the error here
  try {
    await promise.then(function() {
      throw Error('wow')
    });
  } catch (err) {
    console.log('GOTCHA!!', err);
  }
})()