Node.js 如何使用“控制流”控制函数调用

Node.js 如何使用“控制流”控制函数调用

Node.js 是一个用于构建可扩展和高性能Web应用程序的流行开源平台。Node.js的一个关键特性是它能够高效地处理大量并发连接的能力。使其成为可能的其中一个基本机制是 控制流 - 一种管理Node.js程序中函数调用流程的方式。

在Node.js中,函数经常以异步方式执行。这意味着函数在运行时不会阻塞程序的执行,而是将控制权返回给事件循环。事件循环是Node.js的一个关键组件,用于管理函数和回调函数的执行。

在Node.js中,通常使用以下三种方法来管理控制流: 回调函数Promiseasync/await

1. 回调函数: 回调函数是作为参数传递给其他函数的函数,在该函数完成任务后执行。在Node.js中,许多函数是异步的,并且经常将回调作为参数。当异步操作完成时,回调函数被执行,允许程序继续执行。

使用回调函数的步骤:

  1. 定义一个接受回调参数的函数。该函数应执行某些异步操作,然后使用结果调用回调函数。
  2. 调用该函数时,将回调函数作为参数传递。此回调函数将在异步操作完成后执行。
  3. 在回调函数内部,你可以处理异步操作的结果。

语法:

function functionName(param1, param2, callback){
    // Asynchronous operation
    callback(result);
}

示例1:

const multiply = (a, b, callback) => { 
  
    // Multiply the values of a and b 
    const result = a * b; 
  
    // Pass the result to the callback function 
    callback(result);  
} 
  
multiply(2, 3, (result) => { 
  
    // Log "Callback" to the console 
    console.log("Callback");  
  
    // Log the result with a prefix "Ans: " 
    console.log("Ans: " + result);  
});

输出

Callback
Ans: 6

在上面的示例中, multiply 函数接受两个数字作为参数,以及一个在乘法完成时执行的回调函数。回调函数仅将结果记录到控制台中。箭头函数语法被用来定义 multiply 函数和回调函数。

示例2:

// Function that performs an asynchronous operation 
// and invokes a callback when done 
const fetchData = (url, callback) => { 
  
    // Simulating an asynchronous operation  
    // (e.g., making an API request) 
    setTimeout(() => { 
        const data = { id: 74, name: "Geeks for Geeks" }; 
        callback(data); 
    }, 2000); // Simulating a 2-second delay 
} 
  
// Callback function that handles the fetched data 
const handleData = (data) => { 
    console.log("Fetched data:", data); 
} 
  
// Call the fetchData function with the 
// URL and the callback function 
fetchData("https://example.com/api/data", handleData);

输出

Fetched data: { id: 74, name: 'Geeks for Geeks' }

在上述示例中, fetchData 函数通过使用 setTimeout 来模拟异步操作(例如进行API请求)。在模拟延迟之后,它调用回调函数 callback 并将获取到的数据传递给它。 回调函数 handleData 接收到获取到的数据并对其进行一些操作。在这种情况下,它将数据记录到控制台。当我们调用 fetchData 函数时,我们传递了URL和回调函数 handleData2. Promises: Promise是JavaScript中处理异步操作的一种方式。它们提供了一种替代回调函数的方法,更容易编写和管理异步代码。Promise表示一个目前可能还不可用但将来可用的值。当值变为可用时,Promise就会被实现,相关代码将被执行。这样可以更高效和灵活地处理异步操作,并有助于避免回调地狱。Promise是使用Promise构造函数创建的,该构造函数接受一个定义要执行的操作的函数作为参数。一旦操作完成,Promise就会被解决或拒绝,并执行适当的代码。Promise可以使用then()方法链接在一起,以定义更复杂的工作流程。 定义Promise的步骤:

  1. 使用Promise构造函数创建一个Promise,该构造函数接受带有resolve和reject参数的函数。
  2. 使用resolve函数来实现带有一个值的Promise,或使用reject函数来拒绝带有错误的Promise。
  3. 使用.then()和.catch()方法处理Promise的实现和拒绝状态。

语法:

function functionName(){
    return new Promise(function(resolve, reject){
        // Operation 
    });
}

functionName()
    .then(result)
.catch(error);

示例1:

// Function that divides two numbers 
// and returns a promise 
function divide(a, b) { 
    return new Promise(function (resolve, reject) { 
        if (b === 0) { 
  
            // Reject the promise with an 
            // error if b is zero 
            reject(new Error("Cannot divide by zero")); 
        } else { 
            // Resolve the promise with  
            // the result of the division 
            resolve(a / b); 
        } 
    }); 
} 
  
// Call the divide function with arguments 10 and 2 
divide(10, 2) 
    .then(function (result) { 
  
        // Log "Promise" to the console 
        console.log("Promise");  
  
        // Log the result with a prefix "Ans: " 
        console.log("Ans: " + result);  
    }) 
    .catch(function (error) { 
  
        // Log any errors that occurred 
        // during the division 
        console.log(error);  
    });

输出

Promise
Ans: 5

在上面的示例中, divide 函数返回一个Promise,该Promise解析为将 a 除以 b 的结果。如果 b 为零,该Promise将被拒绝并附带错误信息。然后,该Promise在 then 方法中用于处理Promise的完成(即当结果可用时),并使用 catch 方法处理Promise的拒绝(即发生错误时)。在这种情况下,除法的结果将被记录在控制台中。

示例2:

// Function that performs an asynchronous 
// operation and returns a promise 
function getUser(id) { 
    return new Promise(function (resolve, reject) { 
  
        // Simulating an asynchronous  
        // operation (e.g., fetching 
        // user data from a database) 
        setTimeout(() => { 
            const users = { 
                1: { id: 73, name: "Geek" }, 
                2: { id: 74, name: "Geeks for Geeks" }, 
                3: { id: 75, name: "M." } 
            }; 
  
            if (users[id]) { 
  
                // Resolve the promise with 
                // the user data if found 
                resolve(users[id]); 
            } else { 
  
                // Reject the promise with an 
                // error if user not found 
                reject(new Error("User not found")); 
            } 
        }, 2000); // Simulating a 2-second delay 
    }); 
} 
  
// Call the getUser function with user ID 2 and  
//handle the promise using then and catch 
getUser(2) 
    .then(function (user) { 
  
        // Log the retrieved user data to 
        // the console 
        console.log("User:", user); 
    }) 
    .catch(function (error) { 
  
        // Log any errors that occurred during 
        // the asynchronous operation 
        console.log("Error:", error); 
    });

输出

User: { id: 74, name: 'Geeks for Geeks' }

在上面的示例中, getUser 函数接受一个用户ID作为参数,并返回一个promise。在promise内部,我们使用 setTimeout 来模拟异步操作。在模拟的延迟之后,我们检查给定ID的用户是否存在于我们的示例用户数据中。

如果找到用户,我们用用户数据解析promise。如果找不到用户,我们用错误拒绝promise。

我们使用用户ID 2调用 getUser 函数,并使用 thencatch 方法处理promise。 then 方法用于处理解析的promise并接收用户数据。 catch 方法用于处理异步操作期间发生的任何错误。

当promise被解析时,我们将检索到的用户数据记录到控制台。如果有任何错误,我们将记录错误消息。

3. Async/await: 异步/等待是Node.js中的一种语言特性,允许开发人员编写看起来类似于同步代码的异步代码。它被认为是处理异步操作比使用回调或promise更优雅且可读性更强的方式。

通过在函数声明之前使用async关键字标记函数,该函数变为一个始终返回promise的异步函数。可以在async函数内部使用await关键字,以暂停其执行,直到它等待的promise解析或拒绝。然后,由promise返回的值由async函数返回。

这使得可以编写看起来像同步代码的异步代码,使其更易于理解和维护。它还避免了处理嵌套回调时可能出现的回调地狱问题。

使用Async/await的一些步骤:

  1. 在函数声明之前使用async关键字定义异步函数。
  2. 在异步函数内部,使用await关键字暂停函数,直到promise被解决或拒绝。
  3. 在使用await时,确保其后的表达式是一个promise。如果它不是一个promise,它将被隐式转换为一个具有表达式值的解决的promise。
  4. 使用try-catch块处理可能被等待的promise抛出的任何错误。
  5. 调用异步函数,并像处理常规的promise一样,使用.then()和.catch()处理已解决或拒绝的promise。

    语法:

async function functionName(){
    await wait(ms); 
}

functionName().catch(() => {});

示例1:

// Function that returns a promise that 
// resolves after a specified time 
function wait(time) { 
    return new Promise( 
        resolve => setTimeout(resolve, time)); 
} 
  
// Async function that demonstrates 
// the usage of async/await 
async function example() { 
  
    // Log a message indicating the  
    // start of the async function 
    console.log("Async/await Starting..."); 
  
    // Wait for 1 second 
    await wait(1000);  
  
    // Log a message after 1 second has passed 
    console.log("One second has passed!"); 
  
    // Wait for 2 seconds 
    await wait(2000);  
  
    // Log a message after 2 more 
    // seconds have passed 
    console.log("Two more seconds have passed!"); 
} 
  
// Call the async function to start 
// the execution 
example();

输出

Async/await Starting...
One second has passed!
Two more seconds have passed!

在以上示例中,我们定义了一个 wait 函数,该函数返回一个在给定时间(以毫秒为单位)后解析的Promise。然后,我们定义了一个 example 异步函数,它使用 await 来暂停执行,直到 wait 函数返回的Promise解析完成。当调用 example 时,它会记录一条消息,等待一秒钟,记录另一条消息,再等待两秒钟,然后记录最后一条消息。因为我们使用了 asyncawait ,所以我们不需要使用回调函数或链接Promise,这可以使我们的代码更易读、更易理解。

示例2:

// Async function that adds two 
// numbers and returns the sum 
async function add(a, b) { 
  
    // Add the numbers a and b 
    const sum = a + b;  
    return sum; // Return the sum 
} 
  
// Async function that demonstrates 
// the usage of async/await 
async function run() { 
  
    // Await the result of adding 2 and 3 
    const result = await add(2, 3); 
  
    // Log a message indicating the  
    // use of async/await 
    console.log("Async/await"); 
  
    // Log the sum with a prefix "Sum is: " 
    console.log("Sum is: " + result); 
} 
  
// Call the async function to 
// start the execution 
run();

输出

Async/await
Sum is: 5

在上面的示例中,add函数被标记为 async ,表示它返回一个Promise。run函数也被标记为 async ,它使用 await 关键字等待add函数返回的Promise解析后再继续执行。

总的来说,在Node.js中,函数调用的控制流可以使用回调、Promise或async/await来管理,具体取决于程序的特定需求和要求。这些机制提供了一种强大且灵活的方式来管理函数调用的流程,使得Node.js开发人员能够构建高效且可扩展的应用程序。

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程