首页 > 解决方案 > Promise.resolve() 返回使用 Array.push() 填充的空数组

问题描述

我有这段代码,我在其中将用户添加到 Firebase 数据库,以及resolve何时Promise完成用户导入。在解析中,我包含了包含已添加用户的数组。添加单个用户时会填充这些数组。代码如下:

return new Promise((resolve, reject) => {
    let usersAdded = [];
    users.map((user, index) => {
        db.ref('/users').push(user, err => {
            if(!err) {
                usersAdded.push(user)
                console.log(`Array at iteration ${index}: ${usersAdded}`)
            }
            if(index == users.length-1){
              resolve({status: true, usersAdded})
            }
        })
    })
})

控制台输出:

Array at iteration 0: [{name: nadir, email: iamnadir10@yahoo.com, creditCard: true}]
Array at iteration 1: [{name: nadir, email: iamnadir10@yahoo.com, creditCard: true}, {name: arslan, email: arslan346@yahoo.com, creditCard: true}]
Array at iteration 2: [{name: nadir, email: iamnadir10@yahoo.com, creditCard: true}, {name: arslan, email: arslan346@yahoo.com, creditCard: true}, {name: farhan, email: farhan1992@gmail.com, creditCard: true}]

虽然当我在 上看到响应时.then(user),它返回一个空数组 ( usersAdded)。用户也会被添加到 Firebase 中。谁能告诉我这里有什么问题?

编辑:

我能够解决它,问题是 Promise 在 db.ref.push 触发回调之前已解决,在该回调中,我正在填充数组,因为它是一个异步操作。

标签: javascriptnode.jsfirebasepromise

解决方案


就像CertainPerformance 在评论中所说的那样,您的代码仅在按顺序调用推送回调的情况下才有效。由于它们很可能是异步的,因此无法保证回调执行的顺序。这意味着如果首先调用最后一个推送回调,则您的承诺已经解决。出于这个原因,您应该使用Promise.all()等到所有推送回调都解决后再处理结果。

return Promise.all(users.map(user => {
    return new Promise(resolve => db.ref('/users').push(user, resolve));
}))
.then(pushResults => { // all push callbacks are resolved
    return pushResults
        .map((error, index) => error ? null : users[index])
        .filter(Boolean);
});

但是,如果没有用户成功保存,您可能希望调用拒绝。这使代码更复杂,但如果没有保存用户,您可以在返回的承诺上使用catch 。

// return a resolved promise if the users array is empty
if (!users.length) return Promise.resolve(users);

// handle a non-empty users array
return Promise.all(users.map(user => {
    return new Promise(resolve => db.ref('/users').push(user, resolve));
}))
.then(pushResults => {
    // all users had errors
    if (pushResults.every(Boolean)) 
        return Promise.reject(pushResults);

    // one or multiple users had no errors
    return pushResults
        .map((error, index) => error ? null : users[index])
        .filter(Boolean);
});

在then函数中返回一个不是 promise 的值将被简单地转发到下一个then,就好像你返回了一样Promise.resolve(value)


推荐阅读