IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> ‘async‘ call in a function that does not support concurrency -> 正文阅读

[JavaScript知识库]‘async‘ call in a function that does not support concurrency

swift5.5中加入了async/await

我写了一段这样的代码:

DispatchQueue.global().async { [weak self] in
      self?.test()
     }
 }
    
func test() async {
   
   let m = await cakkBackData4()
   print(m)
}

然后提醒我如下的错误:

‘async’ call in a function that does not support concurrency

确切说就是:await cakkBackData4()的方法必须在async函数中进行调用。即调用者必须是异步的。

如何解决:

添加task 会立马去执行

以下说明如何使用

异步函数或异步方法是一种特殊的函数或方法,可以在执行过程中暂停。这与普通的同步函数和方法不同,后者要么运行到完成,要么抛出错误,要么永不返回。
异步函数或方法仍然做这三件事中的一件,但它也可以在等待的时候在中间暂停。在异步函数或方法的主体中,标记每个可以暂停执行的位置。

func listPhotos(inGallery name: String) async -> [String] {
    let result = // ... some asynchronous networking code ...
    return result
}

调用异步方法时,执行将暂停,直到该方法返回。你在电话前写下await标记可能的暂停点。这就像在调用抛出函数时编写try,以便在出现错误时标记程序流的可能更改。在一个异步方法中,只有当调用另一个异步方法时,执行流才会暂停。暂停从不隐式或抢占式,这意味着每个可能的暂停点都标记为await

示例如下:

let photoNames = await listPhotos(inGallery: "Summer Vacation")
let sortedNames = photoNames.sorted()
let name = sortedNames[0]
let photo = await downloadPhoto(named: name)
show(photo)

由于listPhotos(inGallery:)和downloadPhoto(Name:)函数都需要发出网络请求,因此它们可能需要相对较长的时间才能完成。通过在返回箭头之前写入async,使它们都异步,这样应用程序的其余代码就可以在等待图片准备就绪时继续运行。

为了理解上述示例的并发性,这里有一个可能的执行顺序:

  • 代码从第一行开始运行,一直运行到第一个await。它调用listPhotos(inGallery:)函数,并在等待该函数返回时暂停执行。
  • 当此代码的执行被挂起时,同一程序中的其他一些并发代码会运行。例如,一个长期运行的后台任务可能会继续更新新照片库的列表。该代码也会一直运行到下一个挂起点(由wait标记)或完成。
  • listPhotos(inGallery:)返回后,此代码将从该点开始继续执行。它指定返回给photoNames的值。
  • 定义sortedNames和name的行是常规的同步代码。因为这些线路上没有标记等待,所以没有任何可能的暂停点。
  • 下一个wait标记对downloadPhoto(名为:)函数的调用。这段代码再次暂停执行,直到该函数返回,给其他并发代码一个运行的机会。
  • downloadPhoto(名为:)返回后,其返回值被分配给photo,然后在调用show(:)时作为参数传递。

代码中标记为wait的可能挂起点表明当前代码段可能会在等待异步函数或方法返回时暂停执行。
这也称为产生线程,因为在幕后,Swift会暂停当前线程上的代码执行,并在该线程上运行其他代码。因为带有wait的代码需要能够暂停执行,所以只有程序中的某些地方可以调用异步函数或方法:

任务完成了。sleep(纳秒:)方法在编写简单代码以了解并发如何工作时非常有用。此方法不执行任何操作,但在返回之前至少等待给定的纳秒数。下面是listPhotos(inGallery:)函数的一个版本,它使用睡眠(纳秒:)来模拟等待网络操作:

func listPhotos(inGallery name: String) async throws -> [String] {
   try await Task.sleep(nanoseconds: 2 * 1_000_000_000)  // Two seconds
   return ["IMG001", "IMG99", "IMG0404"]
}

上一节中的listPhotos(inGallery:)函数在数组的所有元素就绪后立即异步返回整个数组。另一种方法是使用异步序列一次等待集合的一个元素。下面是在异步序列上迭代的情况:

import Foundation

let handle = FileHandle.standardInput
for try await line in handle.bytes.lines {
   print(line)
}

上面的例子没有使用普通for in循环,而是在for之后使用wait编写for。与调用异步函数或方法一样,写入wait表示可能的挂起点。for await in循环可能会在每次迭代开始时暂停执行,此时它正在等待下一个元素可用。

用wait调用异步函数一次只运行一段代码。当异步代码运行时,调用方等待该代码完成,然后继续运行下一行代码。例如,要从图库中获取前三张照片,您可以等待对downloadPhoto(名为:)函数的三次调用,如下所示:

let firstPhoto = await downloadPhoto(named: photoNames[0])
let secondPhoto = await downloadPhoto(named: photoNames[1])
let thirdPhoto = await downloadPhoto(named: photoNames[2])

let photos = [firstPhoto, secondPhoto, thirdPhoto]
show(photos)

这种方法有一个重要的缺点:虽然下载是异步的,并且在下载过程中可以进行其他工作,但一次只能运行一个对downloadPhoto(名为:)的调用。在下一张照片开始下载之前,每张照片都会被完全下载。然而,这些操作不需要等待每张照片可以独立下载,甚至可以同时下载。

要调用异步函数并使其与周围的代码并行运行,请在定义常数时在let前面写async,然后每次使用该常数时写wait。

async let firstPhoto = downloadPhoto(named: photoNames[0])
async let secondPhoto = downloadPhoto(named: photoNames[1])
async let thirdPhoto = downloadPhoto(named: photoNames[2])

let photos = await [firstPhoto, secondPhoto, thirdPhoto]
show(photos)

func test() async {
        async let m1 = cakkBackData4(1)
        async let m2 = cakkBackData4(2)
        async let m3 = cakkBackData4(3)
        async let m4 = cakkBackData4(7)
        let m = await m1 + m2 + m3 + m4
        print(m)
    }
    
func cakkBackData4(_ n: Int) async -> Int {
    do {
         try await Task.sleep(nanoseconds: UInt64(n * 1_000_000_000))
    } catch {
        
    }
    print(Thread.current)
    return 10
}

在本例中,对downloadPhoto(名为:)的所有三个调用都会在不等待前一个调用完成的情况下启动。如果有足够的可用系统资源,它们可以同时运行。
这些函数调用都没有标记为wait,因为代码不会挂起以等待函数的结果。相反,执行会一直持续到定义照片的那一行,此时程序需要这些异步调用的结果,因此您需要等待写入以暂停执行,直到所有三张照片都完成下载。

以下是您如何看待这两种方法之间的差异:

  • 当下面几行的代码取决于该函数的结果时,使用wait调用异步函数。这将创建按顺序执行的工作。
  • 在代码后面不需要结果时,使用async let调用异步函数。这就产生了可以并行进行的工作。
  • wait和async都允许其他代码在挂起时运行。
  • 在这两种情况下,都用wait标记可能的暂停点,以指示执行将暂停(如果需要),直到异步函数返回。
任务和任务组

task是可以作为程序的一部分异步运行的工作单元。所有异步代码都作为某个任务的一部分运行。上一节中描述的async-let 语法为您创建了一个子任务。您还可以创建一个任务组,并将子任务添加到该组中,这样可以更好地控制优先级和取消,并允许您创建动态数量的任务。

任务按层次结构排列。任务组中的每个任务都有相同的父任务,每个任务都可以有子任务。由于任务和任务组之间的明确关系,这种方法被称为结构化并发。尽管您承担了一些正确性方面的责任,但任务之间明确的父子关系允许Swift处理一些行为,比如传播取消,并允许Swift在编译时检测一些错误。

此处待补充~

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-18 17:32:12  更:2022-04-18 17:36:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 1:42:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码