Bootstrap

回调和承诺以API和谐共处

In this article, we'll learn how to update a callback-based API to support Promises as well.

在本文中,我们将学习如何更新基于回调的API以支持Promises。

First, what is an API, or application programming interface? It's sometimes referred to as a module. It is a collection of methods and variables developers can utilize in their own application.

首先,什么是API或应用程序编程接口? 有时称为模块 。 它是开发人员可以在自己的应用程序中使用的方法和变量的集合。

Watch the accompanying Real Coding episode here.

此处观看随附的Real Coding情节。

回调函数 (Callback Functions)

Many JavaScript API’s and modules provide a final parameter in their methods for something called a callback method. Most of the time you’ll see this defined as done, next, callback, or cb (abbreviation for callback). Callback functions are incredibly useful because they enable other developers get more out of your function such as error handling and asynchronous requests.

许多JavaScript API和模块在其方法中为称为回调方法的事物提供了最终参数。 大多数情况下,您会看到此定义为donenextcallbackcb (callback的缩写)。 回调函数非常有用,因为它们使其他开发人员从您的函数中获得更多收益,例如错误处理和异步请求。

For example, an API method may produce a variety of errors and these errors, if not properly handled, can bring down an entire application. An API utilizing callback methods should be returning all Error objects as the first parameter in the callback. It is assumed that the first parameter in a callback function is always an error instance.

例如,API方法可能会产生各种错误,并且这些错误(如果未正确处理)会导致整个应用程序崩溃。 使用回调方法的API 应该返回所有Error对象作为回调中的第一个参数。 假定回调函数中的第一个参数始终是错误实例。

The function below is a simple example. Its purpose is to double the parameter x and return it via the specified callback function. error starts as null. If any of the conditional checks fail, an Error instance is assigned to error . Then if error exists (it is not null or undefined), then we do not double x and we set the variable double as null; otherwise, x is doubled and assigned to the double variable. After everything is done the function doublePositiveOnly will return the callback method with the first parameter referencing the error variable and the second parameter referencing the double variable.

下面的函数是一个简单的示例。 其目的是将参数x加倍,然后通过指定的callback函数将其返回。 errornull开始。 如果任何条件检查失败, error Error实例分配给error 。 然后,如果存在error (它不是null或未定义),则我们不对x进行双x ,而是将变量double设置为null ; 否则,将x加倍并分配给double变量。 完成所有操作后,函数doublePositiveOnly将返回回调方法,其中第一个参数引用error变量,第二个参数引用double变量。

function doublePositiveOnly(x, callback) {
  let error
  if ( !x )
    error = new Error('x must be defined')
  if ( typeof x !== 'number' )
    error = new Error('x must be a number')
  if ( x < 0 )
    error = new Error('x must be positive')
    
  const double = error ? null : x * 2
  
  return callback(error, double)
}

How would you use this function?

您将如何使用此功能?

doublePositiveOnly(16, function (err, result) {
  if (err) console.error(err.message)
  console.log(result)
})

承诺功能 (Promise Functions)

Promise functions in production are easy to recognize as they utilize .then and .catch methods to return information back to the user. Nearly all callback functions can be replaced by promises, so lets rebuild our doublePositiveOnly method using promises.

在生产中承诺的功能很容易识别,因为他们利用.then.catch方法将信息返回给用户。 几乎所有的回调函数都可以由doublePositiveOnly代替,因此让我们使用doublePositiveOnly重建我们的doublePositiveOnly方法。

function doublePositiveOnly( x ) {
  return new Promise(function (resolve, reject) {
    let error
    if ( !x )
      error = new Error('x must be defined')
    if ( typeof x !== 'number' )
      error = new Error('x must be a number')
    if ( x < 0 )
      error = new Error('x must be positive')
      
    error ? reject(error) : resolve(x * 2)
  })
}

The above function serves the exact same purpose of the callback implementation. However, this version no longer takes a callback method as a parameter. Instead it either rejects an error or resolves the result. You can use this method like so:

上面的函数与回调实现的目的完全相同。 但是,此版本不再将回调方法作为参数。 而是rejects错误或resolves结果。 您可以这样使用此方法:

doublePositiveOnly(16).then(function (result) {
  // do cool stuff with the result
  console.log(result)
}).catch(function (err) {
  // oh no an error! Handle it however you please
  console.error(err.message) 
})

The readability of a Promise function is much clearer than a callback function as you can easily handle the result as well as any potential errors. There is a lot more to Promises functions I did not cover here, and I encourage you to learn as much as you can about them.

Promise函数的可读性比回调函数清晰得多,因为您可以轻松处理结果以及任何潜在的错误。 我在这里没有介绍的Promises功能还有很多,我鼓励您尽可能多地学习它们。

回调和承诺一起 (Callbacks and Promises Together)

We have callbacks and we have promises. They are interchangeable and both satisfy similar needs. Now consider the scenario where we have an API that only supports callback methods. This API is downloaded 1000x times and is now running in production on countless applications. But now the maintainer wants to support Promises as well. Can they do this while also maintaining callback support? YES!

我们有回调,也有承诺。 它们是可互换的,并且都满足类似的需求。 现在考虑以下情形:我们有一个仅支持回调方法的API。 该API的下载次数是1000倍,现在可以在无数应用程序的生产环境中运行。 但是现在,维护者也希望支持Promises。 他们可以在保持回调支持的同时做到这一点吗? 是!

Lets look at the callback implementation of doublePositiveOnly once again, but now also with promise support:

让我们再次看一下doublePositiveOnly的回调实现,但现在也有了promise支持:

function doublePositiveOnly(x, callback) {
  const func = this.doublePositiveOnly
  
  if ( callback === undefined ) {
    return new Promise(function (resolve, reject) {
      func(x, function (err, result) {
        err ? reject(err) : resolve(result)
      })
    })
  }
  
  let error
  if ( !x )
    error = new Error('x must be defined')
  if ( typeof x !== 'number' )
    error = new Error('x must be a number')
  if ( x < 0 )
    error = new Error('x must be positive')
  
  const double = error ? null : x * 2
  
  return callback(error, double)
}

And just like that the doublePositiveOnly method now supports promises as well. It works because first it stores the reference to the function in the func variable. Next, it checks if a callback was passed to the function. If not it returns a promise that passes down the x parameter to another doublePositiveOnly call, and it includes a callback function. This callback function either rejects or resolves the promise just like the promise-only implementation did.

就像doublePositiveOnly方法现在也支持promise一样。 之所以起作用,是因为首先将对函数的引用存储在func变量中。 接下来,它检查是否向函数传递了回调。 如果不是,它将返回一个承诺,该承诺将x参数传递给另一个doublePositiveOnly调用,并包括一个回调函数。 就像仅承诺的实现一样,此回调函数将rejectsresolves承诺。

What is great about this solution is you can use just about anywhere and you don’t have to edit any parts of the original function! You can see it in action in a module I recently contributed to called fastify-jwt. Both the requestVerify and replySign methods support both callbacks and promises.

该解决方案的优点在于,您几乎可以在任何地方使用它,而无需编辑原始功能的任何部分! 您可以在我最近提供的名为fastify-jwt的模块中看到它的运行情况。 无论是requestVerify replySign方法支持回调和promise。

If you have any questions please reach out!

如有任何疑问,请与我们联系!

You can follow me on Github and Twitter or check out my website.

您可以在GithubTwitter上关注我,或者查看我的网站

Keep up the good work.

保持良好的工作。

~Ethan Arrowood

〜伊桑·阿罗德

翻译自: https://www.freecodecamp.org/news/callbacks-and-promises-living-together-in-api-harmony-7ed26204538b/

;