如何在 JavaScript 中等待函数完成
本教程将介绍 JavaScript 的 回调
、承诺
和 Async/await
,并告诉你如何等待一个异步函数完成后再继续执行。
要了解什么是 Promises
和 Async/await
,我们首先要了解 JavaScript 中的 Sync
和 Async
函数是什么。
同步编程一次执行一条命令。当我们调用一个函数执行一个长期运行的动作时,它会停止程序,直到它完成。
JavaScript 是传统的单线程,即使是多核也是如此。我们可以让它只在一个叫做主线程的单线程上运行任务。
这样的同步行为是多线程的限制因素,但可以帮助用户编写代码而不用担心并发问题。
而在异步编程中,长期运行的动作会在主线程以外的另一个线程中执行,所以主线程的执行不会被阻塞。当该长期运行的函数完成后,主程序会被告知并获得访问结果。
JavaScript 中的大多数 I/O 基元都是非阻塞的。网络请求、文件系统操作都是非阻塞操作。被阻塞是 JavaScript 中的例外。
由于 JavaScript 是基于异步编程技术,所以有多种方法,如 回调
、承诺
和 async/await
,使你能够把你的函数按顺序执行。这样,一个代码块或一个函数不会在另一个特定函数完成之前被执行。
上图显示了两个函数异步和同步执行的明显变化。
如果我们有同步语句,那么执行这些语句之后就可以直接执行。
function one(){
console.log("I am function One");
}
function Two(){
console.log("I am function Two");
}
one();
Two();
输出:
I am function One
I am function Two
假设我们要执行两个函数,functionOne()
和 functionTwo()
,这样 functionOne()
应该在执行完 functionTwo()
里面的一些异步语句后执行。
function functionOne(_callback){
// do some asynchronus work
_callback();
}
function functionTwo(){
// do some asynchronus work
functionOne(()=>{
console.log("I am a callback");
});
}
functionTwo();
在执行上述代码时,最后在控制台中打印的是 I am a callback
。著名的 callback
例子是 setTimeout
函数,在超时后要执行一个处理函数。
function testCallBack(){
console.log("log before use setTimeout function");
setTimeout(()=>{
console.log("inside timeout");
},5000);
console.log("log after use setTimeout function");
}
testCallBack();
输出:
log before use setTimeout function
log after use setTimeout function
inside timeout
promise
是一个代表异步操作的最终实现或失败的对象,我们用一个或多个 then
语句将实现回调附加到 promise
上。我们用一个或多个 then
语句将实现回调附加到 promise
上,并在 catch
中调用错误处理回调。
doFirstThing()
.then(result => doSecondThing(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
console.log("The final result thing"+finalResult);
})
.catch(failureCallbackfunction);
}
像上面的例子一样把 then
和 catch
语句链起来,是承诺的优势之一。我们承诺一旦 doFirstThing()
被满足,就会 doSecondThing(result)
。then
的参数是可选的,但如果你必须返回一个结果,则需要。
如果出现错误,浏览器会在链的最后寻找 catch
并执行。这和著名的 try-catch
非常相似。
下面的例子将帮助我们理解 promises
链,并告诉我们如何等待一个具有异步行为的函数完成执行后才能继续执行。
var resolvedFlag = true;
let mypromise = function functionOne(testInput){
console.log("Entered function");
return new Promise((resolve ,reject)=>{
setTimeout(
()=>{
console.log("Inside the promise");
if(resolvedFlag==true){
resolve("Resolved");
}else{
reject("Rejected")
}
} , 2000
);
});
};
mypromise().then((res)=>{
console.log(`The function recieved with value ${res}`)
}).catch((error)=>{
console.log(`Handling error as we received ${error}`);
});
输出:
Entered function
Inside the promise
The function received with value Resolved
创建一个承诺可以像返回一个新的 Promise()
一样简单。Promise()
构造函数接收一个函数作为参数,它应该有两个参数-resolve
和 reject
。
万一我们的事件实现了,需要返回结果,当成功完成我们正在做的事情时,我们使用 resolve()
函数。但如果发生了错误,需要处理,我们使用 reject()
将错误发送到 catch
。
我们设置标志 resolvedFlag = true
来模拟 catch
中的错误处理。如果 resolvedFlag
设置为 false
,则调用 reject()
函数,在 catch
块中处理错误。
输出:
Entered function
Inside the promise
Handling error as we received Rejected
在 JavaScript 的异步环境中,另一种等待函数执行后再继续执行的方法是使用 async/wait
。
async
函数是由 async
关键字声明的函数,而在 async
函数内部只允许使用 await
关键字,用于暂停 async 函数内部的进度,直到实现或拒绝基于承诺的异步操作。
async
和 await
关键字以更简洁的风格实现了基于承诺的异步行为。
让我们来了解一下 async/await
是如何工作的。我们要等待的函数应该返回一个 Promise 类的实例,在调用它之前使用 await 关键字等待它执行。如上所述,包含 await
语句的函数必须与 async
语句一起声明。
下面的例子展示了如何等待那个基于承诺的函数完成后再继续执行。
function testAsync(){
return new Promise((resolve,reject)=>{
//here our function should be implemented
setTimeout(()=>{
console.log("Hello from inside the testAsync function");
resolve();
;} , 5000
);
});
}
async function callerFun(){
console.log("Caller");
await testAsync();
console.log("After waiting");
}
callerFun();
输出:
Caller
Hello from inside the testAsync function
After waiting
相关文章
在 Angular 中上传文件
发布时间:2023/04/14 浏览次数:71 分类:Angular
-
本教程演示了如何在 Angular 中上传任何文件。我们还将介绍如何在文件上传时显示进度条,并在上传完成时显示文件上传完成消息。
Angular 中所有 Mat 图标的列表
发布时间:2023/04/14 浏览次数:91 分类:Angular
-
本教程演示了在哪里可以找到 Angular 中所有 Mat 图标的列表以及如何使用它们。
Angular 2 中的复选框双向数据绑定
发布时间:2023/04/14 浏览次数:139 分类:Angular
-
本教程演示了如何一键标记两个复选框。这篇有 Angular 的文章将着眼于执行复选框双向数据绑定的不同方法。
在 AngularJS 中重新加载页面
发布时间:2023/04/14 浏览次数:142 分类:Angular
-
我们可以借助 windows.location.reload 和 reload 方法在 AngularJS 中重新加载页面。
在 AngularJs 中设置 Select From Typescript 的默认选项值
发布时间:2023/04/14 浏览次数:78 分类:Angular
-
本教程提供了在 AngularJs 中从 TypeScript 中设置 HTML 标记选择的默认选项的解释性解决方案。
在 AngularJS 中启用 HTML5 模式
发布时间:2023/04/14 浏览次数:150 分类:Angular
-
本文讨论如何在 AngularJS 应用程序上启用带有深度链接的 HTML5 模式。
在 AngularJs 中加载 spinner
发布时间:2023/04/14 浏览次数:107 分类:Angular
-
我们将介绍如何在请求加载时添加加载 spinner,并在 AngularJs 中加载数据时停止加载器。
在 Angular 中显示和隐藏
发布时间:2023/04/14 浏览次数:78 分类:Angular
-
本教程演示了 Angular 中的显示和隐藏。在开发商业应用程序时,我们需要根据用户角色或条件隐藏一些数据。我们必须根据该应用程序中的条件显示相同的数据。
在 Angular 中下载文件
发布时间:2023/04/14 浏览次数:104 分类:Angular
-
本教程演示了如何在 angular 中下载文件。我们将介绍如何通过单击按钮在 Angular 中下载文件并显示一个示例。