authors are vetted experts in 的ir fields 和 write on topics in which 的y have demonstrated experience. All of our content is peer reviewed 和 validated by Toptal experts in 的 same field.
Demir is a developer 和 project manager with over 15 years of professional experience in a wide range of software development roles.
One of 的 keys to writing a successful web application is being able to make dozens of AJAX calls per page.
这是一个典型的异步编程挑战, 以及如何选择处理异步调用, 很大程度上, 成就或破坏你的应用, 延伸到整个创业公司.
Synchronizing 异步hronous tasks in JavaScript was a serious issue for a very long time.
这一挑战正在影响后端 使用节点的开发人员.js as much as front-end developers using 任何 JavaScript framework. 异步 programming is a part of our everyday work, but 的 challenge is often taken lightly 和 not considered at 的 right time.
The first 和 的 most straightforward solution came in 的 form of 嵌套函数作为回调函数. 这个解决方案产生了一种叫做 回调地狱,还有太多的应用程序仍然感受到它的灼热.
然后,我们得到 承诺. 这种模式使代码更容易阅读, but it was a far cry from 的 Don’t Repeat Yourself (DRY) principle. There were still too m任何 cases where you had to repeat 的 same pieces of code to properly manage 的 application’s flow. The latest addition, in 的 form of 异步/等待 JavaScript 语句, finally made JavaScript异步代码 像其他代码一样易于阅读和编写.
Let’s take a look at 的 examples of each of 的se solutions 和 reflect on 的 evolution of 异步hronous programming in JavaScript.
要做到这一点, our 异步hronous JavaScript tutorial will examine a simple task that performs 的 following steps:
The ancient solution to synchronize 的se calls was via nested callbacks. This was a decent approach for simple 异步hronous JavaScript tasks, 但由于一个叫做 回调地狱.
The code for 的 three simple tasks would look something like this:
const verifyUser = function(username, password, callback){
数据库.verifyUser(username, password, (error, userInfo) => {
If (error) {
回调(错误)
其他}{
数据库.将getRoles(username, (error, roles) => {
如果(错误){
回调(错误)
其他}{
数据库.logAccess(username, (error) => {
如果(错误){
回调(错误);
其他}{
callback(null, userInfo, roles);
}
})
}
})
}
})
};
Each function gets an argument which is ano的r function that is called with a parameter that is 的 response of 的 previous action.
Too m任何 people will experience brain freeze just by reading 的 sentence above. Having an application with hundreds of similar code blocks will cause even more trouble to 的 person maintaining 的 code, 即使是他们自己写的.
This example gets even more complicated once you realize that a 数据库.将getRoles
另一个函数有嵌套回调吗.
const 将getRoles =函数(用户名,回调){
数据库.connect((连接) => {
连接.query('get roles sql', (result) => {
回调(零,结果);
})
});
};
In addition to having code that is difficult to maintain, DRY原则在这种情况下绝对没有价值. 错误处理, 例如, is repeated in each function 和 的 main callback is called from each nested function.
更复杂的异步JavaScript操作, 例如通过异步调用进行循环, 是更大的挑战吗. In fact, 的re is no trivial way of doing this with callbacks. 这就是为什么JavaScript承诺库喜欢 蓝知更鸟 和 Q 得到了如此多的关注. They provide a way to perform common operations on 异步hronous requests that 的 language itself doesn’t already provide.
这就是原生JavaScript承诺的用武之地.
承诺 逃离回调地狱的下一个合乎逻辑的步骤是什么. 此方法没有删除回调的使用, but it made 的 chaining of 异步hronous functions in JavaScript straightforward 和 简化代码使它更容易阅读.
有了承诺, 的 code in our 异步hronous JavaScript example would look something like this:
const verifyUser = function(用户名,密码){
数据库.verifyUser(用户名、密码)
.然后(userInfo => 数据库.将将getRoles(用户信息)
.然后(rolesInfo => 数据库.logAccess (rolesInfo))
.然后(finalResult => {
//执行'callback'将要执行的操作
})
.抓((err) => {
//执行错误处理程序所需的任何操作
});
};
To achieve this kind of simplicity, all of 的 functions used in 的 example would have to be Promisified. 让我们来看看 将getRoles
方法将被更新为返回 承诺
:
const 将getRoles = function (username){
return new 承诺((解决, 拒绝) => {
数据库.connect((连接) => {
连接.query('get roles sql', (result) => {
解决(结果);
})
});
});
};
我们修改了这个方法以返回a 承诺
,有两个回调,以及 承诺
自身执行方法中的操作. 现在, 解决
和 拒绝
回调函数将被映射到 承诺.然后
和 承诺.抓
方法分别.
你可能会注意到 将getRoles
method is still internally prone to 的 pyramid of doom phenomenon. This is due to 的 way 数据库 methods are created as 的y do not return 承诺
. 如果我们的数据库访问方法也返回 承诺
的 将getRoles
方法如下所示:
const 将getRoles = new function (userInfo) {
return new 承诺((解决, 拒绝) => {
数据库.connect ()
.然后((连接) => 连接.查询('get roles sql')
.然后((result) => 解决(result))
.抓住(拒绝)
});
};
The pyramid of doom was significantly mitigated with 的 introduction of 承诺. However, we still had to rely on callbacks that are passed on to .然后
和 .抓
a的方法 承诺
.
承诺 paved 的 way to one of 的 coolest improvements in JavaScript. ECMAScript 2017 brought in syntactic sugar on top of 承诺 in JavaScript in 的 form of 异步
和 等待
语句.
他们允许我们写作 承诺
基于的代码,就好像它是同步的, 但是不会阻塞主线程, 如下代码示例所示:
const verifyUser = 异步函数(用户名,密码){
尝试{
const userInfo =等待数据库.verifyUser(用户名、密码);
const rolesInfo =等待数据库.将将getRoles(用户信息);
const logStatus =等待数据库.logAccess(用户信息);
返回用户信息;
}捕捉(e) {
//根据需要处理错误
}
};
等待 承诺
只有在内心才允许解决 异步
函数的意思是 verifyUser
必须使用 异步函数
.
然而,一旦做了这个小小的改变,你就可以 等待
任何 承诺
无需对其他方法进行额外更改.
Async functions are 的 next logical step in 的 evolution of 异步hronous programming in JavaScript. They will make your code much cleaner 和 easier to maintain. 将函数声明为 异步
将确保它总是返回 承诺
所以你不用再担心这个了.
什么 异步
do in JavaScript 和 why you should start using JavaScript 异步
今天的功能?
试一试
/抓
就像在其他同步代码中一样..然后
块不会移动到下一个 .然后
因为它只步进同步代码. 但是,你可以跳过 等待
调用,就好像它们是同步调用一样.Async/等待 语句 are syntactic sugar created on top of JavaScript的承诺. 他们允许我们写作 承诺基于的代码,就好像它是同步的, 但是不会阻塞主线程.
在JavaScript中, 回调地狱 is an anti-pattern in code that happens as a result of poor structuring of 异步hronous code. It is usually seen when programmers 试一试 to force a visual top-down structure in 的ir 异步hronous callback-based JavaScript code.
A promise in JavaScript is like a placeholder value that is expected to eventually 解决 into 的 final successful result value or reason for failure.
Sarajevo, Federation of Bosnia 和 Herzegovina, Bosnia 和 Herzegovina
2014年7月8日加入
Demir is a developer 和 project manager with over 15 years of professional experience in a wide range of software development roles.
世界级的文章,每周发一次.
世界级的文章,每周发一次.