如果本文对您有帮助,或者节约了您的时间,欢迎打赏瓶饮料,建立下友谊关系。
本博客不欢迎:各种镜像采集行为。请尊重原创文章内容,转载请保留链接信息。

在上一篇smalltalk的文章中,大家可以了解到:类似smalltalk模拟对话框类的代码,有一个通病,就是说,对话框的显示,是个异步的过程,并不会阻塞js进程。也就是说如果期待一个逻辑在alert完成之后,再执行的话。那么在smalltalk类里面就是个非常难以解决的问题。

因为如果安装老的思路来写代码的话,smalltalk对话框显示出来之后,下面的js逻辑还是会继续执行的,并不会被smalltalk.alert()阻塞在代码逻辑中。这个问题,终于最近有了答案,就是js的async/await。这个天然用于阻塞js进程的好cp组合。大家请跟随苏南大叔的描述,继续学习一下async/awaitsmalltalk中的使用。

smalltalk对话框不阻塞进程

苏南大叔对上一篇smalltalk文章中的例子,做了点小小的改动。代码如下:

var smalltalk = require ('smalltalk/legacy');
console.log("before prompt");
smalltalk.prompt('newsn.net提示您', '这个是苏南大叔测试的prompt范例', 'easy~')
.then(function(value) {
    console.log(value);
}, function() {
    console.log('close');
});
console.log("before alert");
smalltalk.alert('newsn.net提示您', '这个是苏南大叔测试的alert范例')
.then(() => {
    console.log('ok');
});
console.log("before confirm");
smalltalk.confirm('newsn.net提示您', '您看明白了嘛?')
.then(() => {
    console.log('yes');
})
.catch(() => {
    console.log('no');
});
console.log("end all");

从运行结果上,我们就可以看出:在界面上,还停留在第一个对话框,但是从console上面看,程序已经执行完毕。

electron如何利用await解决smalltalk对话框异步执行的问题 - smalltalk_dialog_01

改造版smalltalk

苏南大叔对smalltalk的三个函数,用async/await进行了包装,可以优雅地解决阻塞js进程的问题。

下面可以复习一下async/await的主要要点,不知道官方说法是怎么样的,下面的经验就是苏南大叔自己总结的:

  • await后面的函数必须是个promise,也就是说会带着.then()的一个函数。
  • await必须包裹在一个async修饰的异步函数内。

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/await
https://www.jianshu.com/p/78dfb38ac3d7

下面的这个包装,苏南大叔只是想包装的更加接近于传统的alert系列的写法罢了,毕竟传统的alert是通过返回值来做下一步判断的,而不是then()系列。所以,您使用本来就可以的await也是ok的,没有必要像下面这样包装。下面的包装,仅仅是个怀旧版本的包装罢了。

所以,通过async/await改造过的smalltalk代码如下:

<link rel="stylesheet" href="./node_modules/smalltalk/css/smalltalk.css">
<!--<script src="./node_modules/smalltalk/dist/smalltalk.poly.min.js"></script>-->
<script>
var smalltalk = require ('smalltalk/legacy');
async function alert (title,msg){
  return await smalltalk.alert(title,msg)
  .then(() => {
    return true;
  }).catch((err) => {
    return false;
  });
}
async function confirm (title,msg){
  return await smalltalk.confirm(title,msg)
  .then(() => {
    return true;
  }).catch((err) => {
    return false;
  });
}
async function prompt (title,msg,hint){
  return await smalltalk.prompt(title,msg,hint)
  .then((value) => {
    return value;
  })
  .catch(() => {
    return false;
  });
}
;(async()=>{
  var a = await prompt('newsn.net提示您', '这个是苏南大叔测试的prompt范例', 'easy~');
  var b = await confirm('newsn.net提示您', 'promot 返回值是:'+a);
  await alert('newsn.net发现您点击了:', b?"确定":"取消");
})();

electron如何利用await解决smalltalk对话框异步执行的问题 - smalltalk异步包装

这里值得注意的是:对于不支持require函数的普通浏览器,我们需要用普通的script标签引入smalltalk.poly.min.js。在electron中,需要开启browser的node支持,才可以正常使用require函数。而async/await/promise,在目前最新的chrome浏览器里面,支持性都是很好的。至于ie系列浏览器,鉴于其超强的自暴自弃性,苏南大叔也就暂时不考虑ie系列了。

electron如何利用await解决smalltalk对话框异步执行的问题 - 普通浏览器需要替换js引用

截图特别说明

electron如何利用await解决smalltalk对话框异步执行的问题 - smalltalk异步prompt

electron如何利用await解决smalltalk对话框异步执行的问题 - smalltalk异步confirm

electron如何利用await解决smalltalk对话框异步执行的问题 - smalltalk异步alert

从调用的结果截图上看,每个的smalltalk对话框都得到了上一个对话框的返回值,也就是说对话框变成阻塞式的了。相对于原始的alert/confirm/promot写法,这里的区别除了函数包装外,还有区别的就是如下字样:

;(async()=>{
   var <对话框返回值> = await <被包装过的函数>
})();

结论

本文的调试环境为:win10 + electron(渲染进程)。整体来说,使用async/await包装了smalltalk,然后用覆写了系统函数alert/confirm/promot,就可以完全定制系统对话框了。

美中不足的是:

  • 所有的代码逻辑必须放置在一个匿名的异步函数async里面,才可以正常执行。
  • alert/confirm/promot前面必须增加个await字样,才可以阻塞进程。

更多await相关经验内容,请点击苏南大叔的博客。https://newsn.net/tag/await/

本站采用创作共用版权协议, 要求署名、非商业用途和相同方式共享。
转载本站内容必须也遵循“署名-非商业用途-相同方式共享”的创作共用协议。
程序如此灵动~》下所有原创文章,如被用于商业用途,请您按规定支付稿费。