多个 Promise(ECMAScript 6)

当需要处理多个Promise时,回调函数可能导致代码混乱。Promise.all允许将多个Promise实例组合成一个,当所有Promise都解析后返回一个数组,或者在任何一个Promise拒绝时立即返回错误。async函数提供了一种替代回调的异步处理方式,它返回一个Promise并允许在函数内使用await关键字等待异步操作完成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多个Promise

使用Node-redis操作 redis 时,redis 命令的执行结果在 nodejs 中都体现为回调。

redis.set('foo','bar')
redis.get('foo',(err,reply) => {
    console.log(reply);//bar
})

用回调的形式得到命令执行的结果,对于单条命令还可以应对,当需要连续执行多条命令时,便会遇到“callback hell”,甚至,需要对数组中的每个值都执行一次redis命令,并一次性获得所有执行结果用于后续操作时,使用回调不单单会使代码变得难以读懂,执行结果甚至和预期不同,导致运行结果有逻辑错误。

Promise

代表了未来某个将要发生的事件,Promise 对象将异步操作以同步操作的流程表现出来,避免层层嵌套的回调函数。

Promise对象的详细解释,参考JavaScript标准参考教程 或者 ECMAScript 6 文档,此处只说明所遇到的问题。

页面中表格数据的最后一列,需要挨个从 redis 中查找出来。

function func (id) {
    return new Promise((resolve, reject) => {
        db.hgetall('courses:' + id, (err, reply) => {
            if (reply) {
                resolve({rest: reply.capcatity - reply.selected})
            }
        })
    })
}
let promises = preDefined.ids.map(id => {
    return func(id)
})
Promise.all(promises).then(results => {
    preDefined.rest = results
    for (let index = 0; index < times; index++) {
        let data = courseItem()
        data.courseId = preDefined.ids[index]
        data.courseName = preDefined.courseNames[index]
        data.position = preDefined.position[index]
        data.rest = preDefined.rest[index].rest
        datas.push(data)
    }
    res.status(200).send({datas:datas})
}).catch(reason => {
    console.log('reason:',reason)
})

最开始使用 for 循环去多次调用db.hgetall,再在其回调函数中将返回值push 到一个数组 result,再对此数组进行操作。但结果却是result始终为 undefined,后续操作也就无从谈起。

let result = []
for(let i = 0;i<preDefined.ids.length;i++){
    db.hgetall('courses:' + preDefined.ids[i], (err, reply) => {
        if (reply) {
            result.push({rest: reply.capcatity - reply.selected})
        }
    })
}
preDefined.rest = result //preDefined.rest.length = 0

这个问题的关键在于,就算循环执行db.hgetall,在每个回调函数里,也做不到对 result 不断添加元素,因为程序使用 result 时,回调函数还没有开始执行。

Promise.all([p1,p2,p3])

Promise.all 函数用于将多个 Promise 实例包装成一个实例,其返回值仍然是一个 Promise 实例 p,p的状态由p1,p2,p3决定,分成两种情况。

  • 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
  • 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

async 函数

async 函数也是用来取代回调函数的一种方法。

在函数名前加 async 关键字,就表明此函数内部有异步操作,应该返回一个 Promise 对象,前面用 await 关键字注明,当函数执行时,遇到 await 就会先返回该 Promise 对象,等到触发的异步操作完成,再接着执行函数体内后面的语句。

function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function asyncValue(value) {
  await timeout(50);//先执行timeout函数而不返回,若没有await,则直接返回
  return value;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值