uni-app promise+await容易引起崩溃

uni-app promise+await容易引起崩溃

产品分类:

uniCloud/App

示例代码:

for (let i = 0; i < 1500; i++) {  
    await new Promise((resolve) => setTimeout(resolve, 100))  
    console.log(`${i}`)  
}  

console.log(`all-done`)

操作步骤:

如上

预期结果:

如上

实际结果:

如上

bug描述:

Promise+await比较多的情况下,容易崩溃,以下代码在服务器端必然崩溃。而且没有报错信息,就是一个失败,前面执行的代码打印的日志也能看见。


更多关于uni-app promise+await容易引起崩溃的实战教程也可以访问 https://www.itying.com/category-93-b0.html

15 回复

说下结论吧,在阿里云上面:

定时器触发的函数,可以执行到600秒;
client-call的方式触发,可以执行到10秒多点;

测试方法:

设置超时时间为600
代码里面循环千次,每次sleep 1秒
日志方式做了俩个,一个是控制台log,另外一个是写了一个表做日志

测试结果:

定时器可以实实在在的执行600秒,控制台日志有点乱序,但是数据表的日志是完善的;
client call可以执行到10秒到12秒,客户端超时,而且服务器端也abort了。

其它:

官方更新后的文档说明【非定时触发最高只支持60s超时时间】,这个也是误导性的。client call的服务器端执行时间就是10秒,不是60秒。如果说客户端超时10秒,但是服务器端还可以继续执行50秒,那就可以将结果写入到临时表,然后client去loop结果,这样就可以突破10秒限制了。
腾讯云的云函数测试效果好些,但是即使是付费版,多数资源还不如阿里云的免费版。
我个人是做服务器端的,之前管的app日活千万多,现在的也是几百万。重量级的项目做多了烦了,第一次看见uniapp和unicloud,真的是欣喜若狂。所以希望这个平台越来越完善,看见他走到天尽头。不过在正式使用中,发现很多细节需要打磨,产品文档和功能。写个普通的小玩意,增删改查的的确很容易,超级容易!超级帅!但是系统级的工作稍微繁复一点,就有很多不便利。

更多关于uni-app promise+await容易引起崩溃的实战教程也可以访问 https://www.itying.com/category-93-b0.html


使用中有任何问题都可以提出来,我们会积极采纳用户的意见

回复 DCloud_uniCloud_WYQ: 看见你们会积极采纳,所以我也积极认真的提 :)

为什么要创建这么多的promise

要做复杂点的工作,综合计算,读写外部数据,产生的promise比这个多很多。案例只不过是找到了崩溃的原因后,做的最简sample展示。

是不是云函数超时了,或者内存超出了

超时这样的低级错误不至于。内存更不会超过,这个代码是很小的。

回复 e***@sina.com: 如果是阿里云的话你看到的失败可能只是日志服务的失败。另外你这个云函数执行了150秒是怎么测试的?定时触发还是客户端请求的

回复 DCloud_uniCloud_WYQ: 没有执行那么久,我测试时候,做了很多的不同场景,所以就写个大点的数。 实际上一般执行很难超过13秒,设置的超时是55秒,或者550秒,结果都一样。 范例代码很简单,可以拷贝做个试验,结果一目了然,就不用这样反复的来回沟通了。 我也用了nodejs12来处理,还是跟8一样的。 最大的差别是:本地化运行云函数,就正常的。

回复 e***@sina.com: 沟通还是必要的,因为这个表现在非定时触发调用的情况下是正常的

回复 e***@sina.com: 只有定时触发可以使用10秒以上的超时时间

回复 e***@sina.com: web控制台上非定时触发60秒的描述有误,我们调整下

回复 DCloud_uniCloud_WYQ: 是啊!!我刚才发现了你们修改了控制台的说明,也在别的文档里面找到了!!! 真的是太疯狂了。。。。 文档写的是那样,执行的是另外一样,我发帖时候就怀疑了是10秒的平台限制,但是看见官方的答复一直没有这个。

回复 e***@sina.com: 这个信息之前阿里同步的时候有误,导致文档也写错了,后来找阿里确认了之后忘记改文档了

在uni-app中使用Promise+await处理大量异步操作时,确实可能遇到性能问题甚至崩溃。根据你提供的代码,问题主要在于:

  1. 同步循环中的连续await:你的代码在循环中连续创建了1500个Promise并依次等待,每个间隔100ms。虽然每个Promise本身是异步的,但循环本身是同步的,会快速创建大量微任务。

  2. 内存和堆栈压力:在Node.js环境(uniCloud云函数)或某些App环境下,快速创建大量Promise对象可能导致:

    • 内存使用量激增
    • 事件循环队列过载
    • 垃圾回收压力增大
  3. 超时问题:1500个100ms的等待总共需要150秒(2.5分钟),云函数可能有执行时间限制。

解决方案:

  1. 批量处理:将任务分组处理
async function processBatch(batchSize) {
    for (let i = 0; i < 1500; i += batchSize) {
        const promises = [];
        for (let j = 0; j < batchSize && i + j < 1500; j++) {
            promises.push(new Promise(resolve => 
                setTimeout(() => {
                    console.log(`${i + j}`);
                    resolve();
                }, 100)
            ));
        }
        await Promise.all(promises);
    }
    console.log('all-done');
}
  1. 控制并发:使用专门的并发控制库或简单实现
class TaskQueue {
    constructor(concurrency) {
        this.concurrency = concurrency;
        this.running = 0;
        this.queue = [];
    }
    
    add(task) {
        return new Promise((resolve, reject) => {
            this.queue.push(() => task().then(resolve, reject));
            this.next();
        });
    }
    
    next() {
        while (this.running < this.concurrency && this.queue.length) {
            const task = this.queue.shift();
            this.running++;
            task().finally(() => {
                this.running--;
                this.next();
            });
        }
    }
}
回到顶部