文件从头开始读函数

介绍 (Introduction)

In this article, you will learn how to write your own promisify function from scratch.

在本文中,您将学习如何从头开始编写自己的promisify函数。

Promisification helps in dealing with callback-based APIs while keeping code consistent with promises.

Promisification有助于处理基于回调的API,同时使代码与Promise保持一致。

We could just wrap any function with new Promise() and not worry about it at all. But doing that when we have many functions would be redundant.

我们可以用new Promise()包装任何函数,而完全不用担心。 但是,当我们有许多功能时,这样做将是多余的。

If you understand promises and callbacks, then learning how to write promisify functions should be easy. So let's get started.

如果您了解承诺和回调,那么学习如何编写承诺函数应该很容易。 因此,让我们开始吧。

但是,您是否曾经想知道混杂如何起作用? (But have you ever wondered how promisify works? )

The important thing is not to stop questioning. Curiosity has its own reason for existence.

重要的是不要停止质疑。 好奇心有其存在的原因。

The important thing is not to stop questioning. Curiosity has its own reason for existence.

重要的是不要停止质疑。 好奇心有其存在的原因。

Promises were introduced in the ECMA-262 Standard, 6th Edition (ES6) that was published in June 2015.

在2015年6月发布的ECMA-262标准第6版 (ES6)中引入了承诺。

It was quite an improvement over callbacks, as we all know how unreadable "callback hell" can be :)

与回调相比,这是一个很大的进步,因为我们都知道“回调地狱”是多么难以理解:)

As a Node.js developer, you should know what a promise is and how it works internally, which will also help you in JS interviews. Feel free to review them quickly before reading on.

作为Node.js开发人员,您应该知道什么是诺言以及它如何在内部工作 ,这也将在JS面试中为您提供帮助。 在继续阅读之前,请随时快速阅读它们。

为什么我们需要将回调转换为Promise? (Why do we need to convert callbacks to promises?)

  1. With callbacks, if you want to do something sequentially you will have to specify an err argument in each callback, which is redundant. In promises or async-await, you can just add a .catch method or block which will catch any errors that occurred in the promise chain

    对于回调,如果要顺序执行某项操作,则必须在每个回调中指定一个err参数,这是多余的。 在promise或async-await中,您只需添加.catch方法或块即可捕获promise链中发生的任何错误。

  2. With callbacks, you have no control over when it's called, under what context, or how many times it's being called, which can lead to memory leaks.使用回调,您无法控制何时调用它,在什么上下文中或调用多少次,否则可能导致内存泄漏。
  3. Using promises, we control these factors (especially error handling) so the code is more readable and maintainable.使用promise,我们可以控制这些因素(尤其是错误处理),因此代码更具可读性和可维护性。

如何使基于回调的函数返回承诺 (How to make callback-based functions return a promise)

There are two ways to do it:

有两种方法可以做到这一点:

  1. Wrap the function in another function which returns a promise. It then resolves or rejects based on callback arguments.将函数包装在另一个返回诺言的函数中。 然后,它根据回调参数解析或拒绝。
  2. Promisification — We create a util/helper function promisify which will transform all error first callback-based APIs.

    Promisification —我们创建了一个util / helper函数promisify ,它将转换所有基于错误的基于回调的API。

Example: there’s a callback-based API which provides the sum of two numbers. We want to promisify it so it returns a thenable promise.

示例:有一个基于回调的API,该API提供两个数字的总和。 我们要承诺它,以便它返回可thenable承诺。

const getSumAsync = (num1, num2, callback) => {if (!num1 || !num2) {return callback(new Error("Missing arguments"), null);}return callback(null, num1 + num2);
}
getSumAsync(1, 1, (err, result) => {if (err){doSomethingWithError(err)}else {console.log(result) // 2}
})

兑现诺言 (Wrap into a promise)

As you can see, getSumPromise delegates all the work to the original function getSumAsync, providing its own callback that translates to promise resolve/reject.

如您所见, getSumPromise将所有工作委托给原始函数getSumAsync ,提供其自己的回调,以转换为promise resolve/reject

承诺 (Promisify)

When we need to promisify many functions we can create a helper function promisify.

当我们需要promisify许多功能时,我们可以创建一个helper function promisify

什么是Promisification? (What is Promisification?)

Promisification means transformation. It’s a conversion of a function that accepts a callback into a function returning a promise.

承诺意味着转变。 这是将接受回调的函数转换为返回promise的函数的转换。

Using Node.js's util.promisify():

使用Node.js的util.promisify()

const { promisify } = require('util')
const getSumPromise = promisify(getSumAsync) // step 1
getSumPromise(1, 1) // step 2
.then(result => {console.log(result)
})
.catch(err =>{doSomethingWithError(err);
})

So it looks like a magic function which is transforming getSumAsync into getSumPromise which has .then and .catch methods

所以它看起来像一个神奇的功能它正在改变getSumAsyncgetSumPromise.then.catch方法

让我们编写我们自己的promisify函数: (Let’s write our own promisify function:)

If you look at step 1 in the above code, the promisify function accepts a function as an argument, so the first thing we have to do write a function that can do the same:

如果您看上面代码中的步骤1promisify函数promisify函数接受为参数,因此我们首先要做的是编写一个可以执行相同操作的函数:

const getSumPromise = myPromisify(getSumAsync)
const myPromisify = (fn) => {}

After that, getSumPromise(1, 1) is a function call. This means that our promisify should return another function which can be called with the same arguments of the original function:

之后, getSumPromise(1, 1)是一个函数调用。 这意味着我们的promisify应该返回另一个函数,该函数可以使用与原始函数相同的参数来调用:

const myPromisify = (fn) => {return (...args) => {}
}

In the above code you can see we are spreading arguments because we don’t know how many arguments the original function has. args will be an array containing all the arguments.

在上面的代码中,您可以看到我们正在散布参数,因为我们不知道原始函数有多少个参数。 args将是一个包含所有参数的数组。

When you call getSumPromise(1, 1) you’re actually calling (...args)=> {}. In the implementation above it returns a promise. That’s why you’re able to use getSumPromise(1, 1).then(..).catch(..).

调用getSumPromise(1, 1) ,实际上是在调用(...args)=> {} 。 在上面的实现中,它返回一个promise。 这就是为什么您可以使用getSumPromise(1, 1).then(..).catch(..)

I hope you’ve gotten the hint that the wrapper function (...args) => {} should return a promise.

希望您得到了包装函数(...args) => {}应该返回promise的提示。

兑现承诺 (Return a promise)

const myPromisify = (fn) => {return (...args) => {return new Promise((resolve, reject) => {})}
}

Now the tricky part is how to decide when to resolve or reject a promise.Actually, that will be decided by the original getSumAsync function implementation – it will call the original callback function and we just need to define it. Then based on err and result we will reject or  resolve the promise.

现在最棘手的部分是如何决定何时resolve or reject承诺。实际上,这将由原始的getSumAsync函数实现决定–它会调用原始的回调函数,而我们只需要定义它即可。 然后根据errresult我们将rejectresolve的承诺。

const myPromisify = (fn) => {return (...args) => {return new Promise((resolve, reject) => {function customCallback(err, result) {if (err) {reject(err)}else {resolve(result);}}})}
}

Our args[] only consists of arguments passed by getSumPromise(1, 1) except the callback function. So you need to add customCallback(err, result) to the args[]which the original function getSumAsync will call accordingly as we are tracking the result in customCallback.

我们的args[]仅包含getSumPromise(1, 1)传递的参数getSumPromise(1, 1)回调函数除外getSumPromise(1, 1) 。 因此,您需要在args[]添加customCallback(err, result) ,当我们在customCallback中跟踪结果时,原始函数getSumAsync将相应地调用customCallback

将customCallback推送到args [] (Push customCallback to args[])

const myPromisify = (fn) => {return (...args) => {return new Promise((resolve, reject) => {function customCallback(err, result) {if (err) {reject(err)}else {resolve(result);}}args.push(customCallback)fn.call(this, ...args)})}
}

As you can see, we have added fn.call(this, args), which will call the original function under the same context with the arguments getSumAsync(1, 1, customCallback). Then our promisify function should be able to resolve/reject accordingly.

如您所见,我们添加了fn.call(this, args) ,它将在相同的上下文中使用参数getSumAsync(1, 1, customCallback)调用原始函数。 然后,我们的承诺功能应能够相应地resolve/reject

The above implementation will work when the original function expects a callback with two arguments, (err, result). That’s what we encounter most often. Then our custom callback is in exactly the right format and promisify works great for such a case.

当原始函数需要一个带有两个参数(err, result)的回调时,上述实现将起作用。 这就是我们最常遇到的问题。 然后,我们的自定义回调将采用完全正确的格式,并且promisify在这种情况下非常promisify

But what if the original fn expects a callback with more arguments like callback(err, result1, result2, ...)?

但是,如果原始的 fn 期望回调包含更多的参数,例如 callback(err, result1, result2, ...) 吗?

In order to make it compatible with that, we need to modify our myPromisify function which will be an advanced version.

为了使其兼容,我们需要修改myPromisify函数,它将是一个高级版本。

const myPromisify = (fn) => {return (...args) => {return new Promise((resolve, reject) => {function customCallback(err, ...results) {if (err) {return reject(err)}return resolve(results.length === 1 ? results[0] : results) }args.push(customCallback)fn.call(this, ...args)})}
}

Example:

例:

const getSumAsync = (num1, num2, callback) => {if (!num1 || !num2) {return callback(new Error("Missing dependencies"), null);}const sum = num1 + num2;const message = `Sum is ${sum}`return callback(null, sum, message);
}
const getSumPromise = myPromisify(getSumAsync)
getSumPromise(2, 3).then(arrayOfResults) // [6, 'Sum is 6']

That’s all! Thank you for making it this far!

就这样! 谢谢您的成功!

I hope you’re able to grasp the concept. Try to re-read it again. It’s a bit of code to wrap your head around, but not too complex. Let me know if it was helpful

文件从头开始读函数_如何从头开始编写自己的Promisify函数相关推荐

  1. 表示自己从头开始的句子_形容从头开始的句子|从头开始的句子3篇

    [www.520z-2.com - 范文大全] 开始①从头起;从某一点起:新的一年~了ㄧ今天从第五课~. ②着手进行:~一项新的工作ㄧ提纲已经定了,明天就可以~写. ③开始的阶段:一种新的工作,~总会 ...

  2. java取余数的函数_左神算法基础:哈希函数和哈希表

    笔者在读研刚开始的时候,偶尔看面经,有这样一个问题:只用2GB内存在20亿个整数中找到出现次数最多的数,当时的我一脸懵逼,怎么去思考,20亿个数?What The Fuck! 但是,看完今天的文章,你 ...

  3. append函数_连载|想用Python做自动化测试?函数的参数传递机制及变量作用域

    " 这一节有点难.看不懂没关系.继续往后学,回头再来看." 10.6 函数参数传递的机制 10.6.1 值传递与引用传递 编程语言的参数传递机制通常有两种: 值传递 拷贝参数的值, ...

  4. python偏函数和高阶函数_【Python入门】8.高阶函数之 匿名函数和偏函数

    目录 高阶函数 匿名函数 lambda 偏函数 高阶函数 匿名函数 lambda lambda,即希腊字母λ.顾名思义,匿名函数没有函数名,在运用时采取lambda x : ...的方式,如lambd ...

  5. sql多语句表值函数_构造一个特殊的多语句表函数来检查SQL Server的运行状况

    sql多语句表值函数 问题 ( The Problem ) Checking the many SQL Servers health conditions is one of the DBA basi ...

  6. memcpy函数_如何理解c语言中的回调函数

    在计算机程序设计中,回调函数,或简称回调,是指通过函数参数传递到其它代码的,某一块可执行代码的引用.这一设计允许了底层代码调用在高层定义的子程序. 这段话不是那么好理解,不同语言实现回调的方式有些许不 ...

  7. 减一天 日期函数_一文掌握excel中的日期函数

    在excel中,因为日期的特殊性,大部分关于日期的运算都要用到特有的函数.对于大多数小伙伴们可能没有专门去学习过日期函数都有哪些?如何运用?可以实现什么样的功能?今天小编就为大家整理出来并详细介绍一下 ...

  8. python怎么用gamma函数_如何通俗的理解伽马(gamma)函数

    如何通俗的理解伽马(gamma)函数 - 直觉,求导和示例 我为什么要在乎garmma分布? 使用伽马函数定义了许多概率分布,例如伽马分布,Beta分布,狄利克雷分布,卡方分布和学生t分布等. 对于数 ...

  9. python中如何调用函数_如何调用python中的内置函数?(实例解析)

    对于第一次接触到python这门编程语言的朋友来说,刚刚开始学习python编程的时候对于python函数调用这一方面的了解比较少,在这篇文章之中我们就来了解一下python怎么调用函数. Pytho ...

最新文章

  1. Nginx-rtmp 直播媒体实时流实现
  2. tp5查询字段相加_tp5 sum某个字段相加得到总数的例子
  3. Hessian Web Service C# 示例
  4. python123第九周测验答案2020_运用python123平台助力编程课教学
  5. 什么是Linux系统调用system call?(Linux内核中设置的一组用于实现各种系统功能的子程序)(区别于标准C库函数调用)核心态和用户态的概念、中断的概念、系统调用号、系统调用表
  6. zcmu-1644 多连块拼图
  7. cc2530i2c可同时接受两个传感器的数据吗_汽车方向及维修_玉树沃尔沃S40方向机,宝马531电子方向机进水可以维修吗...
  8. js模板引擎 之handlebars.js
  9. leetcode力扣75. 颜色分类
  10. 树莓派开机后画面一闪之后黑屏的解决
  11. 第 3 章 JVM 与 GC
  12. vscode中如何拉取git代码_工具 | 手把手教你在VSCode中使用Git
  13. win11亮度调节不见了怎么办 windows亮度调节不见了的解决方法
  14. 初级程序员考试大纲 (转)
  15. profibus GSD文件详解
  16. JAVA验证码识别和tesseract训练过程
  17. 互联网公司去年到今年的大批裁员,难道程序员没有未来了吗?
  18. java面试换背景颜色_正在修生养息,突然收到阿里(蚂蚁)面试电话,四面阿里面经总结...
  19. 第二章 随机变量及其分布
  20. 红黑树详解及其模板类实现

热门文章

  1. 计算机网络太难?如何系统自学计算机网络?
  2. 9203 0409 随堂
  3. python-演练-通过描述符来控制另一个类的实例化参数
  4. linux-mv移动更名-硬链接
  5. MySQL sql trace的使用
  6. Sql Server发布订阅如何添加新表如何不初始化整个快照
  7. mybatis3 配置文件解析
  8. C#中A a=new B()的意义
  9. 20145240《信息安全系统设计基础》第十四周学习总结
  10. AIX6.1下WebLogic的nohup日志按天分割