宝哥软件园

对承诺的深刻理解

编辑:宝哥软件园 来源:互联网 时间:2021-08-30

异步承诺

答应我

Promise.all接收的promise数组是按顺序执行还是一起执行,也就是说返回的结果是按固定顺序执行的吗?

目前有两个答案:

应该同步执行,但这是效率问题。如果您想将其更改为异步执行,该怎么办?有人认为结果是按顺序执行的,也有人认为结果的顺序是不确定的。然后我们根据实现进行解密:

环境是:

vscode 1.20.1节点v 8 . 9 . 0 NPM 5 . 6 . 0的实验代码:

//获取随机数,toFixed为四舍五入的保留小数,0为保留整数,范围为~ 1000 const getrandom=()=(数学。random () * 1000)。to fixed(0);const async task=(taskid)=new promise((resolve)={//一次获取0到1,000的随机数,让time out=getRandom();//打印出传递的ID号taskid=1 start . console . log(` taskid=$ { taskid } start。`);//设置计时时间。函数()相当于()={ 0.} setTimeout(function() {//打印出已执行的taskID和time out onsole . log(` taskID=$ { taskID }及时完成=$ {timeout})。`);//异步成功执行resolve(taskID) },超时);});全部承诺([asyncTask(1),asyncTask(2),asyncTask(3)]。然后(result list={ console . log(' results 3360 ',result list);});实验结果如下:

第一次

taskid=1 start . taskid=2 start . taskid=3 start . taskid=2 finished intime=321 . taskid=3 finished intime=506 . taskid=1 finished intime=932 . results : array(3)[1,2,3]第二次

taskid=1 start . taskid=2 start . taskid=3 start . taskid=1及时完成=243.taskid=及时完成=305.taskid=及时完成=792.results :array (3) [1,2,3]第三次

Taskid=1start。taskid=2start。taskid=3start。taskid=及时完成=380。taskid=及时完成=539。taskid=及时完成=782。结果:数组(3) [1,2,3]补充知识介绍:

//toFixed()方法可以将Number舍入到指定的小数位数。NumberObject.toFixed(num)//num必选。小数位数介于0和20之间,包括0和//20。一些实现可以支持更大的数值范围。如果省略此参数,它将被0替换。Promise构造函数只有一个参数,这是一个称为执行器的函数。执行器有两个参数,即resolve()和reject(),一个用于成功的回调,一个用于失败的回调。

新承诺(函数(解析,拒绝){settimeout (()=解析(5,0))})。然后(v=控制台。log (v))//5请记住,承诺实例只能由解析或拒绝函数返回。并且使用then()或者catch()来获取,在新的Promise中不能直接返回,所以无法获取Promise的返回值。

因此,Promise.all中的任务列表[asynctask (1),asynctask (2),asynctask (3)]是按顺序启动的。但是根据结果来看,它们是异步的,互不阻塞,每个任务的完成时间是不确定的。但是,在所有任务完成后,它们的结果仍然会按顺序映射到resultList,这样它们就可以与Promise.all中的任务列表[asynctask (1)、asynctask (2)、asynctask (3)]一一对应。

深刻理解诺言

可能这里有些人不知道为什么会返回数组。

让我们看看这段代码:

全部承诺([asyncTask(1),asyncTask(2),asyncTask(3)]。然后(result list={ console . log(' results 3360 ',result list);});通常当我们使用异步时,只有一个Promise。现在我们使用all()方法包装多个Promise实例。

语法很简单:只有一个参数,可以迭代一个对象,可以是数组或符号类型。

答应我。全部(可重复)。然后()。catch()在三个承诺实例中通过:

全部承诺([新承诺(功能(解决,拒绝){解决(1) })、新承诺(功能(解决,拒绝){解决(2) })、新承诺(功能(解决,拒绝){解决(3)})])。然后(arr={console。log (arr)//[1,2,3]}),那我们就应该回想一下,了解一下。

因为我们传入了一个数组,所以我们必须返回一个数组,我们将映射我们所说的内容。

Promise.race()

语法与all()相同,但返回值不同。只有当一个实例根据传入的多个Promise实例解析或拒绝,而其他实例不执行时,race才会返回结果。

我们简单看一下这个例子,返回的结果是3,因为我们设置了计时器,第三个Promise执行的最快。

Promise.race([新Promise(函数(解析,拒绝){ setTimeout(()=解析(1,1000))}),新Promise(函数(解析,拒绝){settimeout (()=解析(2,100))}),新Promise(函数(解析,拒绝){settimeout (()=解析(3,10))})])。然后(值={console.log(值

这就是我一直困惑的原因。让我们改革前面的例子。

如下所示:

const getRandom=()=(math . random()* 1000)。toFixed(0);函数测试(taskid){ new promise((resolve)={//获取随机数let timeout=getRandom())从0到1000一次;//打印传递的ID号console . log(` taskid=$ { taskid } start。`);setTimeout(function(){ console . log(` TaskID=$ { TaskID }及时完成=$ { time out } . `));resolve(taskID) },超时);})} promise . all([测试(1),测试(2),测试(3)]。然后(result list={ console . log(' results 3360 ',result list);});先来看看结果。

第一次:

taskid=1 start . taskid=2 start . taskid=3 start . results 3360 array(3)[未定义,未定义,未定义]taskid=1及时完成=460.taskid=及时完成=704.taskid=及时完成=883

task id=1 start . task id=2 start . task id=3 start . results 3360 array(3)[未定义,未定义,未定义]task id=2及时完成time=17.taskid=及时完成time=212.taskid=及时完成=612。

task id=1 start . task id=2 start . task id=3 start . results 3360 array(3)[undefined,Undefined,Undefined] taskid=3及时完成=130。taskid=1及时完成=256。taskid=2及时完成=593。

从输出结果中,我们可以看到返回数组中的所有数据都是未定义的。我们需要找出原因,也就是为什么要用箭头函数。

首先,我通过调试寻找它

如图所示:

程序先打印出来

TaskID=1 start . TaskID=2 start . TaskID=3 start。

这意味着它必须先被执行

console . log(` TaskID=$ { TaskID } start . `);因此,我们把断点放在这一段来逐步调试,如下所示:

根据上图,我们可以看到console . log(taskid=$ { taskid } start。)每次都会执行,setTimeout也会执行,但是三次之后,那么()就会被直接执行,所以我们找到了原因,Promise.all()没有等到返回完整的数据,然后()也没有等到解析。

说明有一个异常,这个异常是因为Promise.all()中的参数有一个函数,使得这个比较混乱。因此,我们需要使用对象,或者更准确地说,例子。

注意:

以这段代码为例:

var p1=Promise.resolve(1),p2=Promise.resolve(2),P3=promise . resolve(3);Promise.all([p1,p2,p3])。然后(函数(结果){ console.log(结果);//[1, 2, 3]});在上面的方法中,当promise数组中的所有promise实例都变成resolve时,该方法将返回并将所有结果传递给结果数组。如果承诺数组中的任何承诺被拒绝,整个承诺调用将立即终止,并将返回一个新的拒绝承诺对象。拒绝的使用示例如下:

var p1=承诺.解决(1),p2=承诺.拒绝(2),p3=承诺.解决(3);答应我。全部([P1,p2,P3])。然后(function(results){//然后方法将不被执行console . log(results);}).将执行catch(函数(e){ //catch方法,输出结果为2 console . log(2);});以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。

更多资讯
游戏推荐
更多+