首页 > 解决方案 > 有条件地返回承诺或回调的包装函数

问题描述

async function wait(callback){
  var awaited = await giveError();
  return returner(awaited, callback)
}


function giveError(){throw new Error('oops')}

我的任务是在那里创建returner函数,如果没有回调,它将返回一个承诺,如果确实存在则调用回调

如果returner只返回它的第一个参数,它什么都不做,它会根据需要返回一个承诺

async function returner(awaited, callback){
  console.log('triggering returner')
  if(!callback){
    return awaited
  } else {
    console.log('there is a callback')
  }
}

wait().then(console.log).catch(err=>{
  console.log('correct error catching here for async \n\n')
})

// prints 'correct error catching here for async'

问题是如果有回调我很难捕捉到错误(假设awaited是一个承诺)

wait(function(err, val){
  console.log('callback error handling', err, val)
})

async function returner(awaited, callback){
  console.log('triggering returner')
  if(!callback){
    return awaited
  } else {
    awaited
    .then(val=>{
      callback(null, val)
    })
    .catch(err=>{
      callback(err)
    })
  }
}

// gives UnhandledPromiseRejectionWarning: Error: oops

我有问题:

为什么“触发返回者”从不打印?

awaited一个承诺?如果没有,是否有可能编写returner函数?

标签: javascriptasync-await

解决方案


为什么“触发返回者”从不打印?

因为它的await行为就像throw它正在等待的承诺被拒绝一样。因此代码在那里终止并且错误冒泡,return returner(..)永远不会到达。

正在等待一个承诺?

不,它是承诺的解决值。


我实际上会编写一个函数来包装异步函数本身并接受回调:

  const withCallback = fn => (...args) => {
    const last = args[args.length - 1];
    if(typeof last === "function") {
      return fn(...args.slice(0, -1))
         .then(res => last(null, res))
         .catch(last);
   } else {
      return fn(.. args);
   }
 };

这样你就可以把它写成:

 const wait = withCallback(async function wait(){
   var awaited = await giveError();
   return "result";
 });

这允许您执行以下操作:

 wait().then(/*...*/).catch(/*...*/)
 // As well as
 wait(function(error, result) { /*...*/ });

推荐阅读