搜索
您的当前位置:首页js异步for循环的介绍

js异步for循环的介绍

时间:2023-11-29 来源:乐玩宠

这篇文章主要介绍了关于js 异步for循环的介绍,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

假设一名厨师,需要做3道菜,声明一个菜数组,菜对象是菜名和做菜需要的时间

let dishes=[{name:"fish",time:1},{name:"fish1",time:2},{name:"fish3",time:3}]

首先,厨师做菜应该一道接一道的做,所以得保证一道菜做后才开始做下一道菜。这里用async/await实现,当然也可以选择都用Promise

 (async ()=>{ for (let d of ds) { console.log("开始做"+d.name) await (() => { return new Promise(res => { setTimeout(res, d.time * 1000) }) })(); console.log("做好了"+d.name) } })

小编还为您整理了以下内容,可能对您也有帮助:

js的基本循环类型有哪些

js的基本循环类型有:for循环、while循环、do-while循环、for-in循环。

本篇文章就给大家介绍js的基本循环类型有哪些,如何实现循环,让大家对js循环有一个简单的了解,希望对你们有所帮助。

在JavaScript中支持的循环类型,基本上可以分为四种:for循环、while循环、do-while循环、for-in循环,下面我们就来具体的介绍一下这四种循环类型。【相关视频教程推荐:JavaScript教程】

js for循环

for循环是先判断条件是否为真,再执行{}里的代码块(如果{}里的代码块只有一条语句,{}可省略)。

作用:当已知循环迭代的次数时,则可以使用它循环迭代固定次数的代码块。

语法:

for(表达式1;表达式2;表达式3)

{

要执行的代码块

}说明:

表达式1:声明循环的变量,并初始化变量。

表达式2:循环的判断条件

表达式3:循环的增量,是用来更新循环的一个变量(可以是递增的,也可以使递减的)

注:for循环里的多个表达式之间需要用分号“;”隔开,且for循环里的表达式是都可以省略的,但是必须有两个“;”存在,不可省略,即可以是for(;;)的形式 。

执行流程图:

例:for循环的简单示例

<script>

for (i=1; i<=5; i++)

{

document.write(i + "<br/>")

}

</script>效果图:

在这个例子中,声明了一个变量i,给变量i赋值为1;只有当变量i的值小于等于5时才可以执行{}里的语句块;for循环每结束一次,变量i的值就增加1。

js while循环:

while循环,也是先判断在执行指定的代码块

作用:当指定的条件表达式为真时,循环指定的代码块;当不知道循环迭代的次数时,则可以使用它循环迭代次数达到无限多的元素代码块。

语法:

while(条件表达式)

{

要执行的代码块

}注:在while循环里的条件表达式中,不管条件表达式运算后得到的结果是什么类型的,最后都会转为逻辑值:真和假。

执行流程图:

例:while循环的简单例子

<script>

var i=11;

while (i<=15)

{

document.write(i + "<br/>");

i++;

}

</script>效果图:

为了不让while循环变成一个是死循环,会在while循环的执行代码块中添加“增量”,用来更新判断循环变量。

do-while循环:

do-while循环是先执行再判断,无论条件表达式里的结果是真还是假,代码至少会执行一次。

语法:

do{

要执行的代码

} while(条件表达式);执行流程图:

例:do while循环的简单例子

<script>

var i=21;

do{

document.write(i + "<br/>");

i++;

}while (i<=25);

</script>运行结果:

for-in循环:

作用:主要用于循环遍历对象的属性

语法:

for(keys in zhangsan)

{

要执行的代码

}例:

var obj = {

a: 1,

b: "lian"

};

//给obj定义一个不可枚举的属性c

Object.defineProperty(obj, "c", {

value: 2,

emumerable: false,

writable: true,

configurable: true

});

//虽然属性c不可枚举,但是值依然存在

console.log(obj.c); //2

for (var i in obj) {

//只会遍历可枚举属性

console.log(obj[i]); //1 lian

}运行结果:

总结:

关于javascript循环的问题。

因为你的画棋盘的四条语句,一次画四个格子,所以我只能一次画四个格子,方法是把这四条语句写到一个函数中,并返回false(这样可以让Javascript程序暂停执行),这样我们就可以每次调用函数画四个格子,直到画完棋盘.

完整的Javascript程序如下

<!DOCTYPE html>

<html>

<head>

<title>canvas test</title>

</head>

<body>

 <canvas id='canvas' width="400" height="400"></canvas>

</body>

<script type='text/javascript'>

function ht(i,j,ctx){

 ctx.fillRect(i*80,j*80,40,40);

 ctx.fillRect(i*80+40,j*80+40,40,40);

 ctx.strokeRect(i*80+40,j*80,40,40);

 ctx.strokeRect(i*80,j*80+40,40,40);

 return false;

}

var canv=document.getElementById('canvas');

var ctx=canv.getContext('2d');

for (var j=0; j<4 ; j++)

{

 for (var i=0; i<4; i++)

 {

  ht(i,j,ctx);

  alert('OK');

 }

}

</script>

</html>

关于javascript循环的问题。

因为你的画棋盘的四条语句,一次画四个格子,所以我只能一次画四个格子,方法是把这四条语句写到一个函数中,并返回false(这样可以让Javascript程序暂停执行),这样我们就可以每次调用函数画四个格子,直到画完棋盘.

完整的Javascript程序如下

<!DOCTYPE html>

<html>

<head>

<title>canvas test</title>

</head>

<body>

 <canvas id='canvas' width="400" height="400"></canvas>

</body>

<script type='text/javascript'>

function ht(i,j,ctx){

 ctx.fillRect(i*80,j*80,40,40);

 ctx.fillRect(i*80+40,j*80+40,40,40);

 ctx.strokeRect(i*80+40,j*80,40,40);

 ctx.strokeRect(i*80,j*80+40,40,40);

 return false;

}

var canv=document.getElementById('canvas');

var ctx=canv.getContext('2d');

for (var j=0; j<4 ; j++)

{

 for (var i=0; i<4; i++)

 {

  ht(i,j,ctx);

  alert('OK');

 }

}

</script>

</html>

JS 的异步遍历,你真的会写吗?

我们有时候需要遍历数组的元素,将它们传入到异步函数中执行,其中的异步写法容易写错,我们来看一下有哪些易错点。

假设我们有个异步方法 sleepPromise,形式如下:

这里为了方便演示,使用 setTimeout 写成了个 promise 形式的 sleep 方法。传入的 t 为延迟执行的时间,msg 为信息内容。

在实际开发中,异步方法可能是传入用户好友 id 查找数据库,获得简单的好友信息。

假设我们需要在下面代码的注释位置下方写一个异步便利实现。

通常前端一看到要遍历数组,就会用 forEach。如果你不够老道,可能会写出如下的实现:

输出结果为;

这种写法并不对,其实是将遍历写成了同步。

问题出在哪?出在 forEach 本身并不支持异步写法,你在 forEach 方法的前面加不加 await 关键字都是无效的,因为它的内部没有处理异步的逻辑。

forEach 是 ES5 的 API,要比 ES6 的 Promise 要早的多得多。为了向后兼容,forEach 以后也不会支持异步处理。

所以 forEach 的执行并不会阻塞 loopAsync 之后的代码,所以会导致阻塞失败,先输出 [end] 。

使用普通的 for 循环写法,await 的外层函数就仍就是 loopAysnc 方法,就能正确保存阻塞代码。

但这里的问题是,这些异步方法的执行是 串行 的。可以看到总共执行了 6 s。

如果我们的这些请求是有顺序的依赖关系的,这样写是没问题。

但如果我们的场景是根据用户 id 数组从数据库中查找对应用户名,我们的时间复杂度就是 O(n) ,是不合理的。

此时我们需要改写为 并行 的异步,并且还要保证所有异步都执行完后才执行下一步。我们可以用 Promise.all() 。

首先,我们需要根据 tasks 数组生成对应的 promise 对象数组,然后传入到 Promise.all 方法中执行。

这样,这些异步方法就会同时执行。当所有异步都执行完毕后,代码才往下执行。

输出结果如下:

3 秒就完事了,太强了。

前面说到 forEach 底层并没有实现异步的处理,才导致阻塞失效,那么我们其实不妨实现支持异步的简易 forEach。

并行实现:

串行实现:

用法:

简单总结一下。

一般来说,我们更常用 Promise.all 的并行执行异步的方法,常见于数据库查找一些 id 对应的数据的场景。

for 循环的串行写法适用于多个异步有依赖的情况,比如找最终推荐人。

forEach 则是纯粹的错误写法,除非是不需要使用 async/await 的情况。

js,for循环是怎么运行的?

JavaScript中的循环语句有for循环语句和while循环语句,接下来的这篇文章就给大家先介绍一下JavaScript中for循环语句的用法。

JavaScript

我们先来简单看一下for循环语句和while循环语句的区别

简单来说,for循环语句和while循环语句的主要区别在于当循环次数固定时,使用for循环;当循环次数不固定时,使用while循环。

下面我们就来看看JavaScript中for循环语句的使用方法

for循环语句的语法

for(初始值;条件表达式;增加/减少表达式){   循环处理}

我们来看for循环语句的具体示例

代码如下:变量指定为i

<!DOCTYPE html><html><head><meta charset="utf-8"><title>JavaScript</title></head><body><script>for (var i = 0; i < 10; i++) {document.write (i);}</script></body></html>

首先,虽然它是初始值,但我们声明一个名为i的变量并为其赋值0。这是初始循环过程。

接下来,条件表达式中的i <10意味着在i的值小于10的同时执行处理。

最后一个增加/减少表达式i ++意味着每次执行增加i的值是1。

然后,指定在使用document.write处理文档时要执行的循环过程。

用浏览器输出时...... 输出0到9的值。

JavaScript

在数组中使用for循环

在使用数组编写程序时经常使用for语句的语法。

我们举个例子。

一个名为list的数组框,并在里面放入Tom、Jerry、Holly三个值。

var list = [“Tom”,“Jerry”,“Holly”];

我们使用for语句逐个处理这些值。

首先指定var i = 0作为初始值。只要变量i的值不超过数组的元素数,就循环i。每当循环时,i就加1。

最后,我们使用document.write调用该元素。

for (var i = 0; i < list.length; i++){document.write (list[i]);}

(数组的长度可以通过length属性获得)

变量i是数组元素的下标。因此,它将采用从0到元素数量并访问每个元素(Tom,Jerry,Holly)的计数形式。

我们来运行下面的程序

<!DOCTYPE html><html><head><meta charset="utf-8"><title>JavaScript</title></head><body><script>var list = ["Tom","Jerry","Holly"];for (var i = 0; i < list.length; i++) {document.write (list[i]);}</script></body></html>

运行结果如下

JavaScript

通过这种方式,可以看到正在逐个访问和输出下标为0,1,2的元素。

我们最后来看一下跳转语句:break和continue

跳转语句是在中断当前进程并转移到另一个规范进程时使用的语法。

它主要用于循环进程,可用于for和while语句。

break语句 - 立即终止循环进程

continue语句 - 中断正在执行的循环过程并继续下一个循环过程

下面用for语句来说明一下break和continue。

<script>for (var i = 0; i < 10; i++) {document.write (i * 10);}</script>

break语句

在break语句中,循环进程在i执行到5的时刻退出,并且不再执行。

<script>for (var i = 0; i < 10; i++) {if (i == 5) {break;}document.write (i * 10);}</script>

由于仅执行到i为4时,因此进程在40处终止。

2345截图20181217151306.png

continue语句

另一方面,当执行continue时,仅当i为5时才跳过循环继续执行。

<script>for (var i = 0; i < 10; i++) {if (i == 5) {continue;}document.write (i * 10);}</script>

运行结果如下

2345截图20181217151453.png

js,for循环是怎么运行的?

JavaScript中的循环语句有for循环语句和while循环语句,接下来的这篇文章就给大家先介绍一下JavaScript中for循环语句的用法。

JavaScript

我们先来简单看一下for循环语句和while循环语句的区别

简单来说,for循环语句和while循环语句的主要区别在于当循环次数固定时,使用for循环;当循环次数不固定时,使用while循环。

下面我们就来看看JavaScript中for循环语句的使用方法

for循环语句的语法

for(初始值;条件表达式;增加/减少表达式){   循环处理}

我们来看for循环语句的具体示例

代码如下:变量指定为i

<!DOCTYPE html><html><head><meta charset="utf-8"><title>JavaScript</title></head><body><script>for (var i = 0; i < 10; i++) {document.write (i);}</script></body></html>

首先,虽然它是初始值,但我们声明一个名为i的变量并为其赋值0。这是初始循环过程。

接下来,条件表达式中的i <10意味着在i的值小于10的同时执行处理。

最后一个增加/减少表达式i ++意味着每次执行增加i的值是1。

然后,指定在使用document.write处理文档时要执行的循环过程。

用浏览器输出时...... 输出0到9的值。

JavaScript

在数组中使用for循环

在使用数组编写程序时经常使用for语句的语法。

我们举个例子。

一个名为list的数组框,并在里面放入Tom、Jerry、Holly三个值。

var list = [“Tom”,“Jerry”,“Holly”];

我们使用for语句逐个处理这些值。

首先指定var i = 0作为初始值。只要变量i的值不超过数组的元素数,就循环i。每当循环时,i就加1。

最后,我们使用document.write调用该元素。

for (var i = 0; i < list.length; i++){document.write (list[i]);}

(数组的长度可以通过length属性获得)

变量i是数组元素的下标。因此,它将采用从0到元素数量并访问每个元素(Tom,Jerry,Holly)的计数形式。

我们来运行下面的程序

<!DOCTYPE html><html><head><meta charset="utf-8"><title>JavaScript</title></head><body><script>var list = ["Tom","Jerry","Holly"];for (var i = 0; i < list.length; i++) {document.write (list[i]);}</script></body></html>

运行结果如下

JavaScript

通过这种方式,可以看到正在逐个访问和输出下标为0,1,2的元素。

我们最后来看一下跳转语句:break和continue

跳转语句是在中断当前进程并转移到另一个规范进程时使用的语法。

它主要用于循环进程,可用于for和while语句。

break语句 - 立即终止循环进程

continue语句 - 中断正在执行的循环过程并继续下一个循环过程

下面用for语句来说明一下break和continue。

<script>for (var i = 0; i < 10; i++) {document.write (i * 10);}</script>

break语句

在break语句中,循环进程在i执行到5的时刻退出,并且不再执行。

<script>for (var i = 0; i < 10; i++) {if (i == 5) {break;}document.write (i * 10);}</script>

由于仅执行到i为4时,因此进程在40处终止。

2345截图20181217151306.png

continue语句

另一方面,当执行continue时,仅当i为5时才跳过循环继续执行。

<script>for (var i = 0; i < 10; i++) {if (i == 5) {continue;}document.write (i * 10);}</script>

运行结果如下

2345截图20181217151453.png

js执行顺序+同步异步

按照js同步执行的顺序,函数调用会首先执行for循环,循环5次开启了5个延迟器,延时器内部的回调函数将会异步执行,会在延时1s后进入消息队列等待执行。循环了5次,所以此时i的值为5,然后同步执行console.log打印5,第一次同步执行结束,然后开始执行消息队列的异步任务,打印5个5,中间的undefined是函数调用无返回值返回的。

执行顺序和第一题相同,不同的是延时器被包裹在了一个立即执行函数内容,并把每一次循环的i作为参数传入,此时循环内部的函数形成了一个私有作用域,每一次的i变量被保存了起来,因此每一次循环的i的值都会被打印出来。

延时器内部回调函数是异步函数,将在延时结束后,进入消息队列等待执行,因此同步的console.log("CCCC")最优先执行,然后延时0ms的延时器的回调先进入消息队列,1000ms后第一个延时器的回调再进入消息队列等待执行,因此先执行0ms的回调打印DDDD,再执行1000ms的回调打印BBBB。

这里与上一题不同的是中间多了一个执行3s的同步while循环,因此执行顺序是这样的:

第一个延时器延时1s后内部异步回调函数进入消息队列等待执行,

等待while循环3s后打印"CCCC",

循环结束后第一个延时器内部的回调已经进入消息队列第一个执行位置等待执行。

第二个延时器延时0s后内部异步回调函数进入消息队列等待执行,延时结束后排到第一个延时器的回调函数后面,

因此异步队里内部先打印"BBBB",再打印"DDDD"

jsfor循环应该怎么理解,老师用些数学公式讲

这个是冒泡排序法的经典例子。

运行完后num数组会被被排序

for循环运行的次序是,外层先走一步,然后内层走完,然后外层再走一步,内层再走一圈。

具体来说,
i=0: j依次遍历0,1,2,3,4,5,6,7,程序比较num[0]和num[0-7],只要发现num[0]比某一个数大,就把num[0]和此数交换

这样一来当i=0的时候,j走了一圈后的结果就是把数组的第一个数,也就是num[0]弄成了整个数组中最小的数(也就是3)

接下来i=1; j依次遍历1,2,3,4,5,6,7
结果是num[1]变成剩下数中最小的(也就是5)

然后i=2;j遍历2,3,4,5,6,7

i=3;j走过3,4,5,6,7
.
.
.
最后的结果就是数组被排序了。

jsfor循环应该怎么理解,老师用些数学公式讲

这个是冒泡排序法的经典例子。

运行完后num数组会被被排序

for循环运行的次序是,外层先走一步,然后内层走完,然后外层再走一步,内层再走一圈。

具体来说,
i=0: j依次遍历0,1,2,3,4,5,6,7,程序比较num[0]和num[0-7],只要发现num[0]比某一个数大,就把num[0]和此数交换

这样一来当i=0的时候,j走了一圈后的结果就是把数组的第一个数,也就是num[0]弄成了整个数组中最小的数(也就是3)

接下来i=1; j依次遍历1,2,3,4,5,6,7
结果是num[1]变成剩下数中最小的(也就是5)

然后i=2;j遍历2,3,4,5,6,7

i=3;j走过3,4,5,6,7
.
.
.
最后的结果就是数组被排序了。

JS 中同步和异步的区别是什么?

在JavaScript中,同步和异步是指程序的执行方式。同步是指程序按照代码的顺序依次执行,而异步则是指程序不需要等待某个操作完成后再继续执行其他操作。

同步代码的执行顺序是按照代码的顺序来的,而异步代码则是由事件循环来调度的。当遇到一个耗时的操作时,异步代码会将这个操作放入事件队列中,然后继续执行后面的代码。当这个操作完成时,事件循环会从队列中取出这个操作并执行它。

如何用Promise控制for循环的异步流程

一.定义

promise是对异步编程的一种抽象。它是一个代理对象,代表一个必须进行异步处理的函数返回的值或抛出的异常。也就是说promise对象代表了一个异步操作,可以将异步对象和回调函数脱离开来,通过then方法在这个异步操作上面绑定回调函数。

遵循的是commonJS promise/A+规范。

1.状态

promise有3种状态:pending(待解决,这也是初始化状态),fulfilled(完成),rejected(拒绝)。

2.接口

promise唯一接口then方法,它需要2个参数,分别是resolveHandler和rejectedHandler。并且返回一个promise对象来支持链式调用。

promise的构造函数接受一个函数参数,参数形式是固定的异步任务,举一个栗子:

function sendXHR(resolve, reject){

var xhr = new XMLHttpRequest();

xhr.open('get', 'QueryUser', true);

xhr.onload = function(){

if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304){

resolve(xhr.responseText);

}else{

reject(new Error(xhr.statusText));

}

};

xhr.onerror = function(){

reject(new Error(xhr.statusText));

}

xhr.send(null)

}

二.实现

要实现promise对象,首先要考虑几个问题:

1.promise构造函数中要实现异步对象状态和回调函数的剥离,并且分离之后能够还能使回调函数正常执行

2.如何实现链式调用并且管理状态

首先是构造函数:

//全局宏定义

var PENDING = 0;

var FULFILLED = 1;

var REJECTED = 2;

//Promise构造函数

function Promise(fn){

var self = this;

self.state = PENDING;//初始化状态

self.value = null;//存储异步结果的对象变量

self.handlers = [];//存储回调函数,这里没保存失败回调函数,因为这是一个dome

//异步任务成功后处理,这不是回调函数

function fulfill(result){

if(self.state === PENDING){

self.state = FULFILLED;

self.value = result;

for(var i=0;i<self.handlers.length;i++){

self.handlers[i](result);

}

}

}

//异步任务失败后的处理,

function reject(err){

if(self.state === PENDING){

self.state = REJECTED;

self.value = err;

}

}

fn&&fn(fulfill,reject);

};

构造函数接受一个异步函数,并且执行这个异步函数,修改promise对象的状态和结果。

回调函数方法then:

//使用then方法添加回调函数,把这次回调函数return的结果当做return的promise的resolve的参数

Promise.prototype.then = function(onResolved, onRejected){

var self = this;

return new Promise(function(resolve, reject){

var onResolvedFade = function(val){

var ret = onResolved?onResolved(val):val;//这一步主要是then方法中传入的成功回调函数通过return来进行链式传递结果参数

if(Promise.isPromise(ret)){//回调函数返回值也是promise的时候

ret.then(function(val){

resolve(val);

});

}

else{

resolve(ret);

}

};

var onRejectedFade = function(val){

var ret = onRejected?onRejected(val):val;

reject(ret);

};

self.handlers.push(onResolvedFade);

if(self._status === FULFILLED){

onResolvedFade(self._value);

}

if(self._status === REJECTED){

onRejectedFade(self._value);

}

});

}

测试代码:

function async(value){

var pms = new Promise(function(resolve, reject){

setTimeout(function(){

resolve(value);;

}, 1000);

});

return pms;

}

async(1).then(function(result){

console.log('the result is ',result);//the result is 2

return result;

}).then(function(result){

console.log(++result);//2

});

乐玩宠还为您提供以下相关内容希望对您有帮助:

如何用Promise控制for循环的异步流程

promise是对异步编程的一种抽象。它是一个代理对象,代表一个必须进行异步处理的函数返回的值或抛出的异常。也就是说promise对象代表了一个异步操作,可以将异步对象和回调函数脱离开来,通过then方法在这个异步操作上面绑定回调...

js执行顺序+同步异步

按照js同步执行的顺序,函数调用会首先执行for循环,循环5次开启了5个延迟器,延时器内部的回调函数将会异步执行,会在延时1s后进入消息队列等待执行。循环了5次,所以此时i的值为5,然后同步执行console.log打印5,第一次同...

js的基本循环类型有哪些

在JavaScript中支持的循环类型,基本上可以分为四种:for循环、while循环、do-while循环、for-in循环,下面我们就来具体的介绍一下这四种循环类型。【相关视频教程推荐:JavaScript教程】js for循环for循环是先判断条件是否为真,...

JS 的异步遍历,你真的会写吗?

一般来说,我们更常用 Promise.all 的并行执行异步的方法,常见于数据库查找一些 id 对应的数据的场景。for 循环的串行写法适用于多个异步有依赖的情况,比如找最终推荐人。forEach 则是纯粹的错误写法,除非是不需要使用 ...

关于javascript循环的问题。

1.for循环:for循环是最常用的循环结构之一,它可以按照指定的条件重复执行一段代码。for循环由三个部分组成:初始化表达式、循环条件和循环迭代器。例如:for (var i = 0; i &lt; 5; i++) { console.log(i);} 上述...

for语句循环

for循环语句的控制流介绍:init 会首先被执行,且只会执行一次。这一步允许您声明并初始化任何循环控制变量。您也可以不在这里写任何语句,只要有一个分号出现即可。接下来,会判断 condition。如果为真,则执行循环主体。如果...

什么是for循环语句?

for循环的一般形式为:for(表达式1; 表达式2; 表达式3){语句块}。例如:执行到for语句时,先给 i 赋初值1,判断 i&lt;=100 是否成立;因为此时 i=1,i&lt;=100 成立,所以执行循环体。循环体执行结束后(sum的值为1),...

for循环与forEach循环的区别

3.关于扩展js原生的Array类 使用for循环时,打印每个value值,并不会打印出来扩展js原生的Array类(譬如下图),但使用forEach循环,就可以打印出来。4.关于循环中包含有异步语句 这条区别是我自己根据实践这么认为的,并不是...

js,for循环是怎么运行的?

最普遍的介绍:for循环是JavaScript中最常用的循环,标准for循环代码格式为:for(定义变量初始值;定义变量范围;定义变量自增){ 执行语句 } 举例说明应用场景:for(var i=0;i&lt;10;i++){ console.log(i);} //这样在...

JS里面的for循环里的i代表什么?从i开始循环吗?为什么不用0?

js的for循环有俩种 一种是用来遍历数组 for(xxx ; xxx ; xxx){} 二种是用来遍历json for(xxx in xxx){} 第一种,括号内的表达式,分三块 for(初始化 ; 比较 ; 增量){} 初始化是用来初始化一些变量,可以...

Top
7.440680s