forEach 内的承诺返回

uro*_*may 5 javascript promise angularjs angular-promise

function getNamesById(nameIds) {
    var defer = $q.defer();

    var result = [];
    nameIds.forEach(function (nameId) {
        account.getNameById(nameId).then(function (name) {
            result[nameId] = name;
        });
    });
    defer.resolve(result);
    return defer.promise;
}
Run Code Online (Sandbox Code Playgroud)

我上面的代码显然没有按预期工作。我必须迭代一个 id 数组并构造另一个以 id 作为键的数组,以及从异步函数获取的值

Jam*_*iec 4

你应该使用返回另一个承诺$q.all

function getNamesById(nameIds) {

    var result = [];
    nameIds.forEach(function (nameId) {
        result.push(account.getNameById(nameId));
    });
    return $q.all(result);
}
Run Code Online (Sandbox Code Playgroud)

然后将其链接到其他地方

getNamesById(someNameIds)
     .then(...);
Run Code Online (Sandbox Code Playgroud)

一种更清晰的编写方法是使用.map而不是声明一个数组并使用forEach将其推入其中:

function getNamesById(nameIds) {
    return $q.all(nameIds.map(function (nameId) {
        return account.getNameById(nameId)
    }));
}
Run Code Online (Sandbox Code Playgroud)

如果使用 ES6(并且您的方法肯定会忽略除第一个参数之外的所有参数),则可以进一步简化:

let getNamesById = nameIds => Promise.all(nameIds.map(account.getNameById));
Run Code Online (Sandbox Code Playgroud)

因此,从评论中,我推测您正在尝试获取一个关联数组作为nameId键,并将异步调用的结果作为值。您还需要执行一个步骤 - 您需要从您的返回一个值then,以便稍后使用

function getNamesById(nameIds) {
    return $q.all(nameIds.map(function (nameId) {
        return account.getNameById(nameId)
                    .then(function(name){
                        return {id:nameId, name:name};
                     })
    }));
}
Run Code Online (Sandbox Code Playgroud)

当您使用此方法时,您可以轻松地将reduce结果添加到关联数组中

getNamesById(["a","b","c"])
    .then(function(results){
        var values = results.reduce(function(p,n){
            p[n.id] = n.name;
            return p;
        },{});
        // values is your associative array with keys a,b & c
     });
Run Code Online (Sandbox Code Playgroud)

为了完整起见,用 ES6 写出的内容变得不那么冗长:

function getNamesById(nameIds) {
    return $q.all(nameIds.map(
               nameId => account.getNameById(nameId)
                    .then(name => ({id:nameId, name:name}))
    );
}
Run Code Online (Sandbox Code Playgroud)

getNamesById(["a","b","c"])
    .then(results => {
        var values = results.reduce((p,n) => {
            p[n.id] = n.name;
            return p;
        },{});
        // values is your associative array with keys a,b & c
     });
Run Code Online (Sandbox Code Playgroud)