Javascript 在for循环解析后未定义数组

Javascript 在for循环解析后未定义数组,javascript,arrays,node.js,Javascript,Arrays,Node.js,我有一个未定义数组的问题,它在for循环中被填充后得到解决。如下所示: function mainFunction() { getUnreadMails().then(function(mailArray) { // Do stuff with the mailArray // Here it is undefined }) } function getUnreadMails() { var mailArray = []; ret

我有一个未定义数组的问题,它在for循环中被填充后得到解决。如下所示:

function mainFunction() {
    getUnreadMails().then(function(mailArray) {
        // Do stuff with the mailArray
        // Here it is undefined
    })
}

function getUnreadMails() {
    var mailArray = [];
    return new Promise(function(resolve, reject) {

        listMessages(oauth2Client).then(
            (messageIDs) => {

                for(var i = 0; i < messageIDs.length; i++) {
                    getMessage(oauth2Client, 'me', messageIDs[i]).then(function(r) {
                        // Array gets filled
                        mailArray.push(r);
                    }, function(error) {
                        reject(error);
                    })
                }
                // Array gets resolved
                resolve(mailArray);
            },
            (error) => {
                reject(error);
            }
        )
    });
}
function main函数(){
getUnreadMails().then(函数(mailArray){
//处理邮件数组
//这里没有定义
})
}
函数getUnreadMails(){
var mailArray=[];
返回新承诺(功能(解决、拒绝){
listMessages(oauth2Client)。然后(
(messageid)=>{
for(var i=0;i{
拒绝(错误);
}
)
});
}
listMessages()
getmessages()
都返回一个承诺,因此它被链接在这里。你知道我为什么会得到一个未定义的
邮件数组吗?我的猜测是,当它得到解决时,它还没有被填满。其次,我认为这个流程不是一个好的实践

            getMessage(oauth2Client, 'me', messageIDs[i]).then(function(r) {
                    // Array gets filled
                    mailArray.push(r);
                }, function(error) {
                    reject(error);
                })
是一个异步调用

resolve(mailArray);
不会等待它推送数据,并且会先解析阵列

要解决这个问题,你应该使用Promise.all()

function main函数(){
getUnreadMails().then(函数(mailArray){
//处理邮件数组
//这里没有定义
})
}
函数getUnreadMails(){
var mailArray=[];
返回列表消息(oauth2Client)。然后(
(messageid)=>{
for(var i=0;i{
拒绝(错误);
}
)
}
是一个异步调用

resolve(mailArray);
不会等待它推送数据,并且会先解析阵列

要解决这个问题,你应该使用Promise.all()

function main函数(){
getUnreadMails().then(函数(mailArray){
//处理邮件数组
//这里没有定义
})
}
函数getUnreadMails(){
var mailArray=[];
返回列表消息(oauth2Client)。然后(
(messageid)=>{
for(var i=0;i{
拒绝(错误);
}
)
}

我只是想了解一下marvel308的答案,我认为您需要创建一个新的
承诺
,当您的其他人做出承诺时,该承诺就会得到解决。我还没有机会测试这个,但我认为应该可以

function getUnreadMails() {

    var mailArray = [];

    return new Promise(function(resolve, reject) {

        listMessages(oauth2Client).then(
            (messageIDs) => {

                var messages = [];

                for(var i = 0; i < messageIDs.length; i++) {
                    messages.push(
                        getMessage(oauth2Client, 'me', messageIDs[i]).catch(reject)
                    );
                }

                Promise.all(messages).then(resolve);

            },
            (error) => {
                reject(error);
            }
        )
    });

}
函数getUnreadMails(){ var mailArray=[]; 返回新承诺(功能(解决、拒绝){ listMessages(oauth2Client)。然后( (messageid)=>{ var消息=[]; for(var i=0;i{ 拒绝(错误); } ) }); }

这样,当所有的
消息
都已解决时,就会调用您第一个承诺的
解决
,我想您需要创建一个新的
承诺
,当其他承诺解决时,该承诺会得到解决。我还没有机会测试这个,但我认为应该可以

function getUnreadMails() {

    var mailArray = [];

    return new Promise(function(resolve, reject) {

        listMessages(oauth2Client).then(
            (messageIDs) => {

                var messages = [];

                for(var i = 0; i < messageIDs.length; i++) {
                    messages.push(
                        getMessage(oauth2Client, 'me', messageIDs[i]).catch(reject)
                    );
                }

                Promise.all(messages).then(resolve);

            },
            (error) => {
                reject(error);
            }
        )
    });

}
函数getUnreadMails(){ var mailArray=[]; 返回新承诺(功能(解决、拒绝){ listMessages(oauth2Client)。然后( (messageid)=>{ var消息=[]; for(var i=0;i{ 拒绝(错误); } ) }); }
这样,当所有
消息
都已解析时,就会调用第一个承诺的
解析
,因为数组从未定义,所以数组可能是
未定义的
;至少在你的代码中没有。在循环中的任何迭代能够解决之前,您的承诺就已经解决了,或者更好地说,抛出(尝试
推到未定义)

除此之外。通过使用
Array#map
Promise.all
,您可以大大简化代码

捕捉一个错误,只是为了重现同样的错误,而不做任何其他事情,这是没有意义的

function getUnreadMails() {
    //put this on a seperate line for readability
    //converts a single messageId into a Promise of the result
    const id2message = id => getMessage(oauth2Client, 'me', id);

    return listMessages(oauth2Client)
        //converts the resolved messageId into an Array of Promises
        .then(messageIDs => messageIDs.map( id2message ))
        //converts the Array of Promises into an Promise of an Array
        //.then(Promise.all.bind(Promise));
        .then(promises => Promise.all(promises));
    //returns a Promise that resolves to that Array of values
}
或简称:

function getUnreadMails() {
    return listMessages(oauth2Client)
        .then(messageIDs => Promise.all(messageIDs.map( id => getMessage(oauth2Client, 'me', id) )))
}
.那么(保证,一切)就行不通了

我希望通过将中间结果划分为不同的步骤/函数,使其更加清晰。但是我打字太快了,没有检查。修正了密码

在简短的版本中,mailArray实际上在哪里填充/解析

Promise.all()
接受承诺数组并返回解析值(或第一次拒绝)的单个承诺

messageIDs.map(…)
返回一个数组和周围的承诺。all()将其“转换”为解析值的单个承诺。 由于我们在承诺链中返回这个承诺,所以返回的承诺(
listMessages(oauth2Client)。然后(…)
)也会解析为这个Arra
function mainFunction() {
      getUnreadMails().then(function(mailArray) {
        // Do stuff with the mailArray
        // Here it is undefined
      })
  }

  function getUnreadMails() {
    return new Promise(function(resolve, reject) {
        listMessages(oauth2Client).then(
            (messageIDs) => {
                return Promise.all(messageIDs.map(id => getMessage(oauth2Client, 'me', id)))
       })
      .then((messages) => resolve(messages))
      .catch(error => reject(error))
    });
}