Node.js 未处理的PromisejectionWarning:已调用回调(环回远程方法)

Node.js 未处理的PromisejectionWarning:已调用回调(环回远程方法),node.js,async-await,loopbackjs,es6-promise,Node.js,Async Await,Loopbackjs,Es6 Promise,我得到一个错误,上面写着 (node:27301) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Callback was already called. 根据我对Wait’s和Mozilla描述中拒绝承诺的理解: 如果承诺被拒绝,wait表达式将抛出被拒绝的值 我拒绝回调中围绕我的承诺的错误,如下所示: Airport.nearbyAirports = async

我得到一个错误,上面写着

(node:27301) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Callback was already called.
根据我对Wait’s和Mozilla描述中拒绝承诺的理解:

如果承诺被拒绝,wait表达式将抛出被拒绝的值

我拒绝回调中围绕我的承诺的错误,如下所示:

Airport.nearbyAirports = async (location, cb) => {
  let airports
  try {
    airports = await new Promise((resolve, reject) => {
      Airport.find({
        // code
      }, (err, results) => {
        if (err)
          reject(err) // Reject here
        else
          resolve(results)
      })
    })
  } catch (err) { // Catch here
    cb(err, null)
    return
  }
  if (!airports.empty)
    cb(null, airports)
  }
我的问题是

为什么它仍然认为我的承诺拒绝未处理?我认为
catch
语句应该可以消除这个错误 为什么它会考虑我的回调?我的
catch
中有一个
return
语句,因此不应该调用这两个语句 如果
Airport.find()
抛出异常,则执行将跳转到
catch
块,您的
承诺将永远不会得到解决或拒绝。也许您需要将其包装在自己的
try/catch
中:

Airport.nearbyAirports = async (location, cb) => {
  let airports
  try {
    airports = await new Promise((resolve, reject) => {
      try {
        Airport.find({
          // code
        }, (err, results) => {
          if (err)
            reject(err) // Reject here
          else
            resolve(results)
        })
      } catch (err) {
        reject(err) // Reject here too
        cb(err, null)
      }
    })
  } catch (err) { // Catch here
    cb(err, null)
    return
  }
  if (!airports.empty)
    cb(null, airports)
  }

问题实际上是我的框架(LoopbackJS),而不是我的函数。显然,在撰写本文时,不支持使用承诺:

这意味着我甚至不能在我的函数中使用
wait
,因为远程方法将我的函数包装到其他地方,所以
async
将始终不被处理。我最终回到了基于承诺的内部代码实现:

Airport.nearbyAirports = (location, cb) => {
const settings = Airport.dataSource.settings
const db = DB(settings)
let airports
NAME_OF_QUERY().then((res) => {
  cb(null, res)
}).catch((err) => {
  cb(err, null)
})
同样,loopback3通过允许您使用简单的返回来支持这一点

这:

Entry.findFooById = async (id, cb) => {
  const result = await Entry.findById(id);
  return result;
};
…相当于:

Entry.findFooById = (id, cb) => {
  Entry.findById(id)
    .then(result => cb(null, result))
    .catch(cb);
};

我们使用Loopback 2.31.0,它还支持用于远程方法的异步函数的简单返回。如果将断点放在远程方法的某个位置,并在调用堆栈中跳到其上一级,您将看到它是如何在环回本身()中实现的:

它在这里做什么-它调用您的函数,如果它是异步函数-它将返回一个承诺(
retval.then===“function”
将为
true
)。在这种情况下,作为承诺,环回将正确处理您的结果。它还为您执行错误检查,因此您不再在代码中尝试/捕获块

因此,在您自己的代码中,您只需要像下面这样使用它:

Airport.nearbyAirports = async (location) => {
    let airports = await new Promise((resolve, reject) => {
        Airport.find({
            // code
        }, (err, results) => {
            if (err)
                reject(err) // Reject here
            else
                resolve(results)
        })
    });

    if (!airports.empty)
        return airports;
    }
    else  {
        return {}; // not sure what you would like to return here as it wan not handled in your sample...
    }
}

注意,在这里您根本不需要使用回调(cb)。

是否有可能您解决并拒绝了没有
结果
错误
错误
是由第三方API提供的,当我测试它时,我总是得到
结果
。否则,我的函数将正确返回。但是,这不再使用
await
,这正是我最初的意图。我怎样才能做到这一点?是的。我只是在
Promise
的范围内显示了一个新的
try/catch
。我已经更新了我的代码,包括了您的所有代码,希望能让它更清晰。相关github问题:
Airport.nearbyAirports = async (location) => {
    let airports = await new Promise((resolve, reject) => {
        Airport.find({
            // code
        }, (err, results) => {
            if (err)
                reject(err) // Reject here
            else
                resolve(results)
        })
    });

    if (!airports.empty)
        return airports;
    }
    else  {
        return {}; // not sure what you would like to return here as it wan not handled in your sample...
    }
}