Nodejs如何迭代承诺

时间:2017-10-20 04:46:44

标签: javascript node.js asynchronous

我试图遍历AD用户数组并返回一些用户信息。 我现在一直在寻找几个小时,或者更多,并且无法理解activedirectory2 npm软件包的异步特性。

我正在获得我需要的部分结果,但是当迭代用户名列表时,我只会将第一个打印到控制台。

getADUser.js:

var ActiveDirectory = require('activedirectory2');
var config = require('../../conf/conf-ad.json')
var fileTime = require('./w32FiletimeToEpoch')
var moment = require('moment')
// Find user, return all
var ad = new ActiveDirectory(config);



var getADUser = function (sAMAccountName, opts) {
    return new Promise(function (resolve, reject) {
        ad.findUser(opts, sAMAccountName, function (err, user) {
            if (err) {
                console.log('ERROR: ' + JSON.stringify(err));
                // return;
            }
            if (!user) {
                console.log('User: ' + sAMAccountName + ' not found.');
            } else {
                if (user.userAccountControl == 514) {
                    user.userAccountControl = 'Disabled'
                } else {
                    user.userAccountControl = 'Active'
                }
                if (user.pwdLastSet) {
                    user.pwdLastSet = `${moment(fileTime(user.pwdLastSet))} - ${moment(fileTime(user.pwdLastSet)).fromNow()}`
                }
                if (user.lastLogonTimestamp) {
                    user.lastLogonTimestamp = `${moment(fileTime(user.lastLogonTimestamp))} - ${moment(fileTime(user.lastLogonTimestamp)).fromNow()}`
                }
                if (user.lastLogon) {
                    user.lastLogon = `${moment(fileTime(user.lastLogon))} - ${moment(fileTime(user.lastLogon)).fromNow()}`
                }
                // return;
                // return user.promise();
                // console.log(user)
                // test.push(user)
                resolve(JSON.stringify(user));
            }
        });
    })
}

module.exports = getADUser

checkADCompletions.js:

var checks = ['USERONE', 'USERTWO']

let opts = {
    attributes: ['sAMAccountName', 'userAccountControl']
};
let checkADCompletions = function (userList) {
    let data = []
    return new Promise(function (resolve, reject) {
        return new Promise(function (res, rej) {
            for (let i = 0; i < userList.length; i++) {
                getADUser(userList[i], opts)
                    .then(function (s) {
                        data.push(s)
                    }).then(function () {
                        resolve(data)
                    })
            }
        })
    })
}

checkADCompletions(checks).then(function (d) {
    console.log(d) \\ Only prints the first user details
})

3 个答案:

答案 0 :(得分:1)

您可以像这样使用Promise.all

let checkADCompletions = function (userList) {
    var promises = userList.map(function (user) {
        return getADUser(user, opts);
    })

    return Promise.all(promises);
}

你基本上是在创建一个promises数组,然后同时执行它们。

然后像这样使用它:

checkADCompletions(checks)
.then(function (responses) {
    console.log(responses); // this will be an array
})
.catch(function (err) {
    // if any of the promises fail, it will enter here.
    // err will be the value of the rejected promise
})

Promise.all will fail even if just one of the checked users fail。因此,您需要很好地处理错误,即处理 ad.findUser的任何可能结果:

var getADUser = function (sAMAccountName, opts) {
    return new Promise(function (resolve, reject) {
        ad.findUser(opts, sAMAccountName, function (err, user) {
            if (err || user == null) {
                console.log('ERROR: ' + JSON.stringify(err));
                reject(err);
            }
            if (user.userAccountControl == 514) {
                user.userAccountControl = 'Disabled'
            } else {
                user.userAccountControl = 'Active'
            }
            if (user.pwdLastSet) {
                user.pwdLastSet = `${moment(fileTime(user.pwdLastSet))} - ${moment(fileTime(user.pwdLastSet)).fromNow()}`
            }
            if (user.lastLogonTimestamp) {
                user.lastLogonTimestamp = `${moment(fileTime(user.lastLogonTimestamp))} - ${moment(fileTime(user.lastLogonTimestamp)).fromNow()}`
            }
            if (user.lastLogon) {
                user.lastLogon = `${moment(fileTime(user.lastLogon))} - ${moment(fileTime(user.lastLogon)).fromNow()}`
            }
            resolve(user);
        });
    })
}

答案 1 :(得分:0)

一个简单的解决方法是仅在for循环结束时调用resolve

// checkADCompletions.js
var checks = ['USERONE', 'USERTWO']

let opts = {
    attributes: ['sAMAccountName', 'userAccountControl']
};
let checkADCompletions = function (userList) {
    let data = []
    return new Promise(function (resolve, reject) {
        for (let i = 0; i < userList.length; i++) {
            getADUser(userList[i], opts)
                .then(function (s) {
                    data.push(s)
                }).then(function () {
                    if (i === userList.length) {
                        resolve(data)
                    }
                })
            }
        })
    })
}

checkADCompletions(checks).then(function (d) {
    console.log(d)
})

答案 2 :(得分:-1)

当您致电resolve时,您会关闭承诺。您启动了两个Promise,然后是for循环,并在for循环中调用resolve。因此第一个用户被填充但for循环不会继续,因为Promise已经完成执行。将resolve移到循环之外,你应该好好去。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolve