包装函数,有条件地返回promise或callback

时间:2018-08-20 19:01:28

标签: javascript async-await

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


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

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

如果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函数?

2 个答案:

答案 0 :(得分:1)

  

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

因为如果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) { /*...*/ });

答案 1 :(得分:0)

async函数将 始终 返回Promise。如果您希望将函数的返回类型配置为根据参数而有所不同,则需要手动进行操作:

function foo(cb) {
  if (typeof cb !== "function") {
    return Promise.resolve("hello");
  } else {
    return cb("hello");
  }
}

foo(v => console.log(v));
foo().then(v => console.log(v));