swift 异步 asyncawait 的使用

swift 异步 asyncawait 的使用,第1张

基本使用方式:

方法后面跟上 async 表示是一个异步函数。如果调用异步函数

在正常返回的函数中使用 async 修饰的func时,需要用Task{} 进行包装,否则报错

使用方式:

属性也可以 async properties

使用异步属性,必须只能是 get 属性。可写属性不能使用异步属性。

public func resume(returning x: T) 接收 completion 中的数据返回,转换成 async 函数返回。

public func resume(throwing x: E) 进行抛出异常

withCheckedContinuation 方法中的 checked 会在运行时对 *** 作进行检查:是否调用 resume 进行返回。如果不调用会造成资源泄露。多次调用也会造成问题。

continuation 有且只能 resume 一次。

withUnsafeContinuation 的工作机制和 withCheckedContinuation 一致,唯一区别在于运行时不会对 *** 作进行检查。但性能更好。实际使用中 withCheckedContinuation 测试没有问题后,正式发布时使用 withUnsafeContinuation

使用方式如下:

withCheckedContinuation

如果有抛出异常

withCheckedThrowingContinuation

事情的起因是微服务A通过feign调用微服务B的某个接口,报了形如下的异常

负责微服务A的工程师小张就找到负责提供该接口的工程师小李,问小李是不是改动了接口,小李一脸无辜说他最近没对这个接口做任何改动,不过小李还是说道他排查一下。

小李排查的过程如下,他先通过swagger查看他提供给A服务接口是否存在,他一查发现他在swagger上看不到他提供给A服务的接口。于是他怀疑是不是有人动了他的代码,他就去查找最近的git提交记录,发现没人动他的代码,因为项目还没发布,都在测试阶段,他就根据项目集成的git-commit-id-maven-plugin插件定位到测试目前发布具体是哪个版本。(ps:对

git-commit-id-maven-plugin感兴趣的朋友,可以查看之前的文章聊聊如何验证线上的版本是符合预期的版本)。然后他将该版本的代码下到本地进行调试,他发现代码中提供给A的接口还在,target下的class也有提供给A的接口class,但诡异的是swagger就是没显示他提供出去的接口,他一度以为是swagger出了问题,于是他用postman直接请求他提供A的接口,发现报了404。然后他就叫负责同个微服务B的同事小王,也帮忙试一下,发现结果就是404。后面没招,小李就去求助他们项目资深同事小林。

小林的排查思路如下,他先走查一下小李的接口代码,发现他提供的接口实现层的方法上加了一个@Async,示例形如下

小林凭多年的经验直觉告诉小李说,应该是@Async引起。小李很斩钉截铁的说不可能啊,他@Async很早就加了,之前接口都可以访问的,小林一看小李说得那么肯定,他也不好打击小李。于是他接下来做了如下 *** 作,先在项目中yml配置如下参数,开启springweb日志

然后在项目中加了形如下代码,来跟踪接口bean的类型

启动控制台,看日志形如下

发现确实没打印出相关requestMapping映射信息,这可以说明一点就是小李那个接口没有绑定到springmvc映射,也就是出现404的原因。接着观察控制台打印的bean,内容形如下

这很明显这个接口bean已经被jdk动态代理给替换。小李看到控制台打印的信息,若有所思,然后说,我把@Async去掉试下。小李把@Async去掉后,再观察下控制台

通过控制台可以发现,此时接口已经绑定到springmvc映射,而且打印出bean类型是真实对象bean。小李看到这个现象,也百思不得其解,他说道他之前确实是加了@Async,接口也能正常访问。于是小林就问一句,你确定你加了@Async,异步生效了吗,小李说开启spring异步,不都是加@Async吗。小林又问了一句,你在项目中开启异步,除了加@Async,还有做什么处理吗,小李说没了,他之前在项目使用异步就都是加了@Async,也能用了好好的,小林一听,基本上知道为什么小李之前@Async,接口还能正常访问了,小林为了验证想法,就问同负责该项目的小王,说你最近有加什么异步 *** 作吗,小王说有,小林进一步问,你是怎么做的,小王说,他先加@EnabledAsyn,开启异步,然后在业务逻辑层上的方法上加@Async注解。小李一听,说原来使用@Async还要配合@EnabledAsyn啊,他之前都不知道

接着小李说 那在controller是不是就不能使用@Async注解了? ,小林说最好是把加@Async的逻辑挪到service层去处理,不过也不是controller就不能使用@Async注解了,接着小林为了验证这个想法,他把原来实现的接口类去掉,形如下

启动后,查看控制台

此时bean的类型如下

访问接口,打印内容如下

从控制台可以发现,都是>

微信小程序退出账号的前提条件是用户已登陆,且在前端页面和后端服务已记录了用户的登陆状态。退出登陆的 *** 作,相当于清除用户登陆状态的 *** 作。

因此微信小程序实现退出账号的具体流程包括以下几点:

1、用户登陆 *** 作:

(1)微信小程序调用wxlogin获取登录凭证(code)。

(2) 将code传递到后端服务,通过凭证进而换取用户登录态信息,包括用户的唯一标识(openid),并生成与用户一一对应的token值,保存起来,用作用户身份的校验,同时返回给微信小程序客户端。

(3)微信小程序获取到token令牌,保存到本地,即可作为已登陆状态的凭证。

前端代码为:

const login =  function () {

wxshowLoading({ title: '登陆中' })

wxlogin()then(res => {

if (reserrMsg === 'login:ok') {

Apilogin(rescode)then(data => {

wxhideLoading()

wxsetStorageSync('token', data) })

}})}

后端服务代码为:

async login(jsCode) {

const { ctx, app } = this;

const APPID = appconfigminiProgramappId;

const SECRET = appconfigminiProgramappSecret;

const url = `>

const res = await ctxcurl(url, { method: 'GET', dataType: 'json' });

const openid = resdataopenid;

const session_key = resdatasession_key;

const str = await appredisget(openid);

if (str && JSONparse(str)accessToken) { // 已登陆

const oldAccessToken = JSONparse(str)accessToken;

await appredisdel(oldAccessToken); // 删除token,实现单点登陆

await appredisdel(openid);}

const accessToken = await ctxhelpercreateWxToken(openid, session_key); // 生成新的token

return accessToken;}

2、退出登陆 *** 作:

(1)点击“退出账号”按钮,调用ajax请求后端退出登陆接口并传递用户token,若退出成功,则清除当前用户登陆状态和token信息。

(2)刷新当前页面数据,清除页面上的用户信息。

(3)后端API接收到客户端传递的用户token,查询数据库判断用户是否已登陆,若登陆,则删除或将token置为无效。

前端代码为:

const logout =  function () {

wxshowLoading({ title: '退出登陆中' })

const token = wxgetStorageSync('token')

Apilogout({ token: token })then(data => {

wxhideLoading()

wxremoveStorageSync('token')

refreshPageData()

})}

后端代码为:

async logout(accessToken) {

const { ctx, app } = this;

const userId = await appredisget(accessToken);

if (!userId) ctxthrow(400, '登陆状态已失效');

await appredisdel(userId); // 删除userId

await appredisdel(accessToken); // 删除token

}

扩展资料:

1、微信小程序账号密码登陆和授权登陆后,token保存在loacalStore中,在每次加载接口时,携带上token令牌,向服务端传递已登陆的状态。

2、微信小程序退出登陆需清除登陆状态,当调用微信小程序API中的wxlogin()执行登陆 *** 作,通过登陆接口获取到code后需调用后端接口生成token, 由于安全问题,勿在前端使用密钥生成。在执行退出登陆 *** 作时,需清除localStorage 中缓存的token及用户信息,并刷新当前页面数据。

async function getTitle(){

const title = await drivergetTitle();

consolelog(title)

}

以上是一个minium框架中使用异步获取小程序title的方法,其中,`driver`是minium框架中的驱动对象,`getTitle()`方法用于获取当前页面的title。获取到的title可以通过`consolelog()`方法打印出来。望采纳。

针对小程序的异步

因为懒得去配置async 和await的环境了,wxgetStorageSync是同步的就

直接了在这个基础上了一个重入锁的js来实现同步

/本类主要用来实现同步/

const lockerKey = "wxlocker";

var lockerContainer={};

/

加锁函数

参数:锁名

/

function lock(lockName){

var obj= wxgetStorageSync(lockerKey);

consolelog(111);

consolelog(obj);

if (typeof obj === "undefined" || obj==null||obj==''){

  lockerContainerlockName = 1;

  wxsetStorageSync(lockerKey, lockerContainer);

}else{

  lockerContainer = obj;

  if (typeof lockerContainerlockName !== "undefined" && lockerContainerlockName != null && lockerContainerlockName != ''){

    lockerContainerlockName = lockerContainerlockName +1;

  }else{

    lockerContainerlockName = 1;

  }

  //更新锁

  wxsetStorageSync(lockerKey, lockerContainer);

}

}

/

解锁函数

参数:锁名

/

function unlock(lockName){

  var obj = wxgetStorageSync(lockerKey);

  consolelog(222);

  consolelog(obj);

  if (typeof obj === "undefined" || obj == null || obj == '') {//没有锁过

    return;

  } else {

    lockerContainer = obj;

    if (typeof lockerContainerlockName !== "undefined" && lockerContainerlockName != null && lockerContainerlockName != '') {

      if (lockerContainerlockName <=0){

        lockerContainerlockName=0;

        return;

      }else{

        lockerContainerlockName = lockerContainerlockName - 1;

      }

    } else {

      return;

    }

    //更新锁

    wxsetStorageSync(lockerKey, lockerContainer);

    obj = wxgetStorageSync(lockerKey);

    consolelog(obj);

  }

}

/

是否被锁函数

参数:锁名

返回值:boolean

/

function isLockedBy(lockName){

  var obj = wxgetStorageSync(lockerKey);

  if (typeof obj === "undefined" || obj == null || obj == '') {//没有锁过

    return false;

  } else {

    lockerContainer = obj;

    if (typeof lockerContainerlockName !== "undefined" && lockerContainerlockName != null && lockerContainerlockName != '') {

      if (lockerContainerlockName > 0) {

        return true;

      } else {

        return false;

      }

    } else {

      return false;

    }

  }

}

/

等待函数(等待100millseconds后自动解除)

参数:锁名,间隔毫秒,等待解锁完成后的回调函数

/

function wait(lockName, millseconds,callback){

  //100次监控后清空锁

  var expireTime = 0;

  var timer =setInterval(function () {

    consolelog("wait " + millseconds);

    if (!isLockedBy(lockName)){

      clearInterval(timer);

      callback();

    }else{//被锁住了

      expireTime++;

      if (expireTime > 100) {

        lockerContainerlockName=null;

        //清空锁

        wxsetStorageSync(lockerKey, lockerContainer);

        clearInterval(timer);

      }

    }

  }, millseconds)

}

moduleexports = {

  wait: wait,

  unlock: unlock,

  lock: lock

}

用法,加锁多少次就要解锁多少次

lock("mylock")

lock("mylock")

unlock("mylock")

unlock("mylock")

wait("mylock",1000,callback)

有很多 async 的面试题,例如

等等,需要找出一个规律

用同步的方式,编写异步。

和 Promise 的关系

async 函数返回结果都是 Promise 对象(如果函数内没返回 Promise ,则自动封装一下)

await 后面跟 Promise 对象:会阻断后续代码,等待状态变为 resolved ,才获取结果并继续执行

await 后续跟非 Promise 对象:会直接返回

总结来看:

异步本质

await 是同步写法, 但本质还是异步调用

即,只要遇到了 await ,后面的代码都相当于放在 callback 里。

forof

定时算乘法

执行 async 函数执行返回的是 Promise 对象

await 相当于 Promise 的 then

trycatch 可捕获异常,代替 Promise 的 catch

右上图解读: async返回Promise,await返回then,await后面报错会终止执行,可以用trycatch来捕获

以上就是关于swift 异步 async/await 的使用全部的内容,包括:swift 异步 async/await 的使用、记一次因@Async引发的程序bug、微信小程序退出账号怎么实现等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zz/9778291.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-01
下一篇 2023-05-01

发表评论

登录后才能评论

评论列表(0条)

保存