web前端 - JavaScript 中一流函数的日常用例

30 篇文章 1 订阅

什么是“一流函数”?

维基百科的定义:

在计算机科学中,如果一种编程语言将函数视为一等公民,那么它就被称为具有一等函数。这意味着该语言支持将函数作为参数传递给其他函数,将它们作为其他函数的值返回,并将它们分配给变量或将它们存储在数据结构中。

例如,在 JavaScript 中,我们可以将一个函数分配给一个变量。

var sum = function(a, b) {

return a + b;

}

var total = sum(10, 1);

如果我们是第一次阅读,这个定义会有点混乱。然而,事实是我们在不知情的情况下使用了它。

AddEventListener — 学习 JavaScript 的第一课

过去,引入 JavaScript 是为了向网站添加动态行为。例如,我们希望在用户单击按钮时更改文本。当有人学习 JavaScript 时,这是第一行代码。

The text will change when you click on the button

Click me!

在第 9 行,我们将函数作为参数传递给 addEventListener 方法。该功能与按钮的“单击”事件相关联。当事件被触发时,该函数将运行。

让我们好奇——第 1 部分

要了解该功能的作用,让我们考虑一下它不可用的语言。无论使用何种编程语言,添加动态行为在 UI 开发中都很常见。如果我们不能将函数作为参数传递怎么办?我期待您在留言区与我们分享您的看法。

发送 HTTP 请求——JavaScript 中的常见任务

我以Axios为例。它是最流行的用于发送 HTTP 请求的 JavaScript 库之一。在一个项目中,我们可能需要添加一些常用的配置。

例如,要将 JWT 发送到服务器,我们希望将标头 Authorization 添加到所有请求。因此,我们需要一个函数来抓取 JWT 并将其添加到标题中。

可以使用拦截器来完成。

// Add jwt to all requests using interceptors

axios.interceptors.request.use(function (config) {

const jwt = globalStore.getJWT(); // assume the token is saved in a global store.

config.headers[“Authorization”] = Bearer ${jwt};

return config;

}, null, { synchronous: true });

同样,我们传递 2 个函数作为 use 方法的参数。第一个函数在请求的标头中设置令牌。

如果出现错误,则第二个函数将运行(为简单起见,我们没有在此处定义它)。Axios在处理一个请求时,会一一运行所有的拦截器,将用户的配置转化为完整配置。

然后它将请求发送到服务器。

Axios 处理拦截器的方式很好地说明了 JavaScript 中的一流函数。

// ------------------------------- inside inteceptor’s use method ------------------------//

InterceptorManager.prototype.use = function use(fulfilled, rejected, options) {

this.handlers.push({

fulfilled: fulfilled,

rejected: rejected,

synchronous: options ? options.synchronous : false,

runWhen: options ? options.runWhen : null

});

return this.handlers.length - 1;

};

// -------------------------------- process interceptors ---------------------------------//

// filter out skipped interceptors

var requestInterceptorChain = [];

var synchronousRequestInterceptors = true;

this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) {

if (typeof interceptor.runWhen === ‘function’ && interceptor.runWhen(config) === false) {

return;

}

synchronousRequestInterceptors = synchronousRequestInterceptors && interceptor.synchronous;

requestInterceptorChain.unshift(interceptor.fulfilled, interceptor.rejected);

});

// ------------------------------- execute synchronous interceptors ---------------------//

var newConfig = config;

while (requestInterceptorChain.length) {

var onFulfilled = requestInterceptorChain.shift();

var onRejected = requestInterceptorChain.shift();

try {

newConfig = onFulfilled(newConfig);

} catch (error) {

onRejected(error);

break;

}

}

在第 23 行,我们在 usemethod 中传递的已完成和被拒绝的函数被添加到 requestInterceptorChain。我们将函数存储在数组中。

然后 Axios 将运行它们中的每一个。在 while 循环中,您可以看到函数被分配给要调用的变量。

让我们好奇——第 2 部分

发送 HTTP 请求不限于前端开发。在开发后端部分时,我们可能需要向外部服务器发送请求。您能否向我们解释一下如何以您的首选语言处理 HTTP 请求配置?欢迎在留言区分享您的想法。

在 Node.js 中处理 HTTP 请求

使用 Node.js,我们可以使用 JavaScript 开发后端部分。后端开发是关于处理 HTTP 请求,即:接收它们,解析它们,找到正确的答案,并响应客户端。Node.js 最常用的框架之一是 Express.js。

该框架使用中间件来完成上述任务。以下是 Express 官方页面中中间件的定义:

中间件函数是可以访问请求对象 (req)、响应对象 (res) 和应用程序请求-响应循环中的下一个中间件函数的函数。

您可以在下面看到中间件的示例。

var express = require(‘express’);

var app = express();

app.use(’/users’, function (req, res, next) {

// assume only authenticated users can access to /users route

if(!req.user) {

// non authenticated users

res.json({status : “failed”, message: “Please login!”});

return;

}

// if users is authenticated, go to the next middleware

next();

});

中间件函数在 use 方法中传递。反过来,它接受另一个函数 next 作为参数。最后调用 next 函数,将控制权传递给堆栈中的以下中间件。

Express 因其简单性而广受欢迎并被广泛使用。“一个 Express 应用程序本质上是一系列中间件函数调用。” 尽管看起来微不足道,但 Express 的中间件可以帮助我们完成 Web 服务器的所有任务:记录请求、压缩响应、设置 cookie、防止 XSS 攻击……仅举几例。

让我们再次好奇!

HTTP 请求在其他后端框架中是如何处理的?您能将它与 Express 中间件进行比较吗?每种方法的优点/缺点是什么?你看,有很多问题要研究!

最后但并非最不重要的——JavaScript 中的回调地狱

如您所知,JavaScript 是单线程的。但它提供了一种有效的机制来处理长时间运行的任务。我们可以立即开始下一个任务,而不是等待任务完成,并定义前一个任务完成后我们需要做什么。这就是回调函数的来源——定义在长时间运行的任务后应该运行什么。

import { readFile } from ‘fs’;

readFile(’/etc/passwd’, (err, data) => {

if (err) throw err;

console.log(data);

});

回调函数为我们提供了一个强大的工具来处理 I/O 绑定的应用程序。然而,任何好事如果被滥用都会变坏。您可以查看下面的示例。

fs.readdir(source, function (err, files) {

if (err) {

console.log('Error finding files: ’ + err)

} else {

files.forEach(function (filename, fileIndex) {

console.log(filename)

gm(source + filename).size(function (err, values) {

if (err) {

console.log('Error identifying file size: ’ + err)

} else {

console.log(filename + ’ : ’ + values)

aspect = (values.width / values.height)

widths.forEach(function (width, widthIndex) {

height = Math.round(width / aspect)

console.log('resizing ’ + filename + 'to ’ + height + ‘x’ + height)

this.resize(width, height).write(dest + ‘w’ + width + ‘_’ + filename, function(err) {

if (err) console.log('Error writing file: ’ + err)

})

}.bind(this))

}

})

})

}

})

多个回调函数和 if/else 语句使代码难以理解。如果我们添加更多逻辑,它在未来可能变得不可维护。由于这个问题,引入了更新的功能。Promise 似乎可以帮助我们编写一个更简洁的程序。Async/await 关键字允许我们编写看起来像同步代码的异步代码。

今天爱创课堂小编的分享就到这里了,有想学习前端,了解前端更多知识的同学,欢迎大家私信小编领取前端学习资料,也可以关注,点赞加分享,多多支持小编!!!

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值