Async/awaitIn computer programming, the async/await pattern is a syntactic feature of many programming languages that allows an asynchronous, non-blocking function to be structured in a way similar to an ordinary synchronous function. It is semantically related to the concept of a coroutine and is often implemented using similar techniques, and is primarily intended to provide opportunities for the program to execute other code while waiting for a long-running, asynchronous task to complete, usually represented by promises or similar data structures. The feature is found in C#,[1]: 10 C++, Python, F#, Hack, Julia, Dart, Kotlin, Rust,[2] Nim,[3] JavaScript, and Swift.[4] HistoryF# added asynchronous workflows with await points in version 2.0 in 2007.[5] This influenced the async/await mechanism added to C#.[6] Microsoft first released a version of C# with async/await in the Async CTP (2011). It was later officially released in C# 5 (2012).[7][1]: 10 Haskell lead developer Simon Marlow created the async package in 2012.[8] Python added support for async/await with version 3.5 in 2015[9] adding 2 new keywords, TypeScript added support for async/await with version 1.7 in 2015.[10] JavaScript added support for async/await in 2017 as part of ECMAScript 2017 JavaScript edition. Rust added support for async/await with version 1.39.0 in 2019 using the C++ added support for async/await with version 20 in 2020 with 3 new keywords Swift added support for async/await with version 5.5 in 2021, adding 2 new keywords Example C#The C# function below, which downloads a resource from a URI and returns the resource's length, uses this async/await pattern: public async Task<int> FindSizeOfPageAsync(Uri uri)
{
var client = new HttpClient();
byte[] data = await client.GetByteArrayAsync(uri);
return data.Length;
}
A function using async/await can use as many In the particular case of C#, and in many other languages with this language feature, the async/await pattern is not a core part of the language's runtime, but is instead implemented with lambdas or continuations at compile time. For instance, the C# compiler would likely translate the above code to something like the following before translating it to its IL bytecode format: public Task<int> FindSizeOfPageAsync(Uri uri)
{
var client = new HttpClient();
Task<byte[]> dataTask = client.GetByteArrayAsync(uri);
Task<int> afterDataTask = dataTask.ContinueWith((originalTask) => {
return originalTask.Result.Length;
});
return afterDataTask;
}
Because of this, if an interface method needs to return a promise object, but itself does not require One important caveat of this functionality, however, is that while the code resembles traditional blocking code, the code is actually non-blocking and potentially multithreaded, meaning that many intervening events may occur while waiting for the promise targeted by an var a = state.a;
var client = new HttpClient();
var data = await client.GetByteArrayAsync(uri);
Debug.Assert(a == state.a); // Potential failure, as value of state.a may have been changed
// by the handler of potentially intervening event.
return data.Length;
ImplementationsIn F#In 2007, F# added asynchronous workflows with version 2.0.[14] The asynchronous workflows are implemented as CE (computation expressions). They can be defined without specifying any special context (like The following async function downloads data from an URL using an asynchronous workflow: let asyncSumPageSizes (uris: #seq<Uri>) : Async<int> = async {
use httpClient = new HttpClient()
let! pages =
uris
|> Seq.map(httpClient.GetStringAsync >> Async.AwaitTask)
|> Async.Parallel
return pages |> Seq.fold (fun accumulator current -> current.Length + accumulator) 0
}
In C#In 2012, C# added the async/await pattern in C# with version 5.0, which Microsoft refers to as the task-based asynchronous pattern (TAP).[15] Async methods usually return either Methods that make use of The following async method downloads data from a URL using public async Task<int> SumPageSizesAsync(IEnumerable<Uri> uris)
{
var client = new HttpClient();
int total = 0;
var loadUriTasks = new List<Task<byte[]>>();
foreach (var uri in uris)
{
var loadUriTask = client.GetByteArrayAsync(uri);
loadUriTasks.Add(loadUriTask );
}
foreach (var loadUriTask in loadUriTasks)
{
statusText.Text = $"Found {total} bytes ...";
var resourceAsBytes = await loadUriTask;
total += resourceAsBytes.Length;
}
statusText.Text = $"Found {total} bytes total";
return total;
}
In PythonPython 3.5 (2015)[19] has added support for async/await as described in PEP 492 (written and implemented by Yury Selivanov).[20] import asyncio
async def main():
print("hello")
await asyncio.sleep(1)
print("world")
asyncio.run(main())
In JavaScriptThe await operator in JavaScript can only be used from inside an async function or at the top level of a module. If the parameter is a promise, execution of the async function will resume when the promise is resolved (unless the promise is rejected, in which case an error will be thrown that can be handled with normal JavaScript exception handling). If the parameter is not a promise, the parameter itself will be returned immediately.[21] Many libraries provide promise objects that can also be used with await, as long as they match the specification for native JavaScript promises. However, promises from the jQuery library were not Promises/A+ compatible until jQuery 3.0.[22] Here's an example (modified from this[23] article): async function createNewDoc() {
let response = await db.post({}); // post a new doc
return db.get(response.id); // find by id
}
async function main() {
try {
let doc = await createNewDoc();
console.log(doc);
} catch (err) {
console.log(err);
}
}
main();
Node.js version 8 includes a utility that enables using the standard library callback-based methods as promises.[24] In C++In C++, await (named co_await in C++) has been officially merged into version 20.[25] Support for it, coroutines, and the keywords such as It is worth noting that std::promise and std::future, although it would seem that they would be awaitable objects, implement none of the machinery required to be returned from coroutines and be awaited using co_await. Programmers must implement a number of public member functions, such as #include <iostream>
#include "CustomAwaitableTask.h"
using namespace std;
CustomAwaitableTask<int> add(int a, int b)
{
int c = a + b;
co_return c;
}
CustomAwaitableTask<int> test()
{
int ret = co_await add(1, 2);
cout << "return " << ret << endl;
co_return ret;
}
int main()
{
auto task = test();
return 0;
}
In CThe C language does not support await/async. Some coroutine libraries such as s_task[27] simulate the keywords await/async with macros. #include <stdio.h>
#include "s_task.h"
// define stack memory for tasks
int g_stack_main[64 * 1024 / sizeof(int)];
int g_stack0[64 * 1024 / sizeof(int)];
int g_stack1[64 * 1024 / sizeof(int)];
void sub_task(__async__, void* arg) {
int i;
int n = (int)(size_t)arg;
for (i = 0; i < 5; ++i) {
printf("task %d, delay seconds = %d, i = %d\n", n, n, i);
s_task_msleep(__await__, n * 1000);
//s_task_yield(__await__);
}
}
void main_task(__async__, void* arg) {
int i;
// create two sub-tasks
s_task_create(g_stack0, sizeof(g_stack0), sub_task, (void*)1);
s_task_create(g_stack1, sizeof(g_stack1), sub_task, (void*)2);
for (i = 0; i < 4; ++i) {
printf("task_main arg = %p, i = %d\n", arg, i);
s_task_yield(__await__);
}
// wait for the sub-tasks for exit
s_task_join(__await__, g_stack0);
s_task_join(__await__, g_stack1);
}
int main(int argc, char* argv) {
s_task_init_system();
//create the main task
s_task_create(g_stack_main, sizeof(g_stack_main), main_task, (void*)(size_t)argc);
s_task_join(__await__, g_stack_main);
printf("all task is over\n");
return 0;
}
In Perl 5The Future::AsyncAwait[28] module was the subject of a Perl Foundation grant in September 2018.[29] In RustOn November 7, 2019, async/await was released on the stable version of Rust.[30] Async functions in Rust desugar to plain functions that return values that implement the Future trait. Currently they are implemented with a finite-state machine.[31] // In the crate's Cargo.toml, we need `futures = "0.3.0"` in the dependencies section,
// so we can use the futures crate
extern crate futures; // There is no executor currently in the `std` library.
// This desugars to something like
// `fn async_add_one(num: u32) -> impl Future<Output = u32>`
async fn async_add_one(num: u32) -> u32 {
num + 1
}
async fn example_task() {
let number = async_add_one(5).await;
println!("5 + 1 = {}", number);
}
fn main() {
// Creating the Future does not start the execution.
let future = example_task();
// The `Future` only executes when we actually poll it, unlike JavaScript.
futures::executor::block_on(future);
}
In SwiftSwift 5.5 (2021)[32] added support for async/await as described in SE-0296.[33] func getNumber() async throws -> Int {
try await Task.sleep(nanoseconds: 1_000_000_000)
return 42
}
Task {
let first = try await getNumber()
let second = try await getNumber()
print(first + second)
}
Benefits and criticismsThe async/await pattern is especially attractive to language designers of languages that do not have or control their own runtime, as async/await can be implemented solely as a transformation to a state machine in the compiler.[34] Supporters claim that asynchronous, non-blocking code can be written with async/await that looks almost like traditional synchronous, blocking code. In particular, it has been argued that await is the best way of writing asynchronous code in message-passing programs; in particular, being close to blocking code, readability and the minimal amount of boilerplate code were cited as await benefits.[35] As a result, async/await makes it easier for most programmers to reason about their programs, and await tends to promote better, more robust non-blocking code in applications that require it.[dubious – discuss] Critics of async/await note that the pattern tends to cause surrounding code to be asynchronous too; and that its contagious nature splits languages' library ecosystems between synchronous and asynchronous libraries and APIs, an issue often referred to as "function coloring".[36] Alternatives to async/await that do not suffer from this issue are called "colorless". Examples of colorless designs include Go's goroutines and Java's virtual threads.[37] See alsoReferences
|
Portal di Ensiklopedia Dunia