Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/three.js/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 期待已久的承诺仍在回归<;待定>;_Javascript_Node.js_Asynchronous_Es6 Promise - Fatal编程技术网

Javascript 期待已久的承诺仍在回归<;待定>;

Javascript 期待已久的承诺仍在回归<;待定>;,javascript,node.js,asynchronous,es6-promise,Javascript,Node.js,Asynchronous,Es6 Promise,我有一系列关于人的数据对象。每个person对象都包含0-n个URL,用于获取其他信息(此人的来宾) 我想处理这个列表,调用每个“来宾”URL,并在原始数据集中包含来宾的姓名 上下文:这是一个AWS lambda函数。我在本地运行这个。(lambda local-l index.js-e fixtures/test_event1.json) 我正在成功地使用wait/async检索初始数据集 但我无法得到这些关于客人信息的电话。它总是显示出一个悬而未决的承诺,即使结果还在等待 // index.

我有一系列关于人的数据对象。每个person对象都包含0-n个URL,用于获取其他信息(此人的来宾)

我想处理这个列表,调用每个“来宾”URL,并在原始数据集中包含来宾的姓名

上下文:这是一个AWS lambda函数。我在本地运行这个。(
lambda local-l index.js-e fixtures/test_event1.json

我正在成功地使用wait/async检索初始数据集

但我无法得到这些关于客人信息的电话。它总是显示出一个悬而未决的承诺,即使结果还在等待

// index.js

const fetch = require('node-fetch');

exports.handler = async function(event){

    try {
        let registrations = await getEventRegistrations();
        console.log(registrations);

/* All good here - sample console output
[ { contactId: 43452967,
    displayName: 'aaa, bbb',
    numGuests: 0,
    guestUrls: [] },
  { contactId: 43766365,
    displayName: 'bbb, ccc',
    numGuests: 1,
    guestUrls:
     [ 'https://<URL>' ] },
  { contactId: 43766359,
    displayName: 'ccc, ddd',
    numGuests: 2,
    guestUrls:
     [ 'https://<URL>',
       'https://<URL> ] } ]
*/

        // Expanding the guest URLs is proving problematic - see expandGuests function below
        registrations = registrations.map(expandGuests);
        console.log(registrations);


/* Registrations are just pending Promises here, not the real data

[ Promise { <pending> },
  Promise { <pending> },
  Promise { <pending> } ]

*/

        return {
            statusCode: 200,
            headers: {
                'Access-Control-Allow-Origin': '*',
            },
            body: JSON.stringify(registrations),
        };
    }
    catch (exception) {
        console.log(exception);
        return {
            statusCode: 500,
            body: 'Unable to retrieve data.'
        };
    }
};

function getEventRegistrations() {
    return fetch('<URL>')
    .then(res => res.json())
    .catch(function (error) {
        console.log('Event registrants request failed', error);
        return null;
    });
}

function getGuestName(url) {
    return fetch(url)
    .then(res => res.json())
    .then(guest => guest.DisplayName)
    .catch(function (error) {
        console.log('Guest name request failed', error);
        return null;
    });
}

async function expandGuests(data) {

    const promises = data.guestUrls.map(url => getGuestName(url));
    data.guestNames = await Promise.all(promises);

    return data;
}


//index.js
const fetch=require('node-fetch');
exports.handler=异步函数(事件){
试一试{
让注册=等待getEventRegistrations();
控制台日志(注册);
/*这里一切正常-控制台输出示例
[{联系人ID:43452967,
displayName:'aaa,bbb',
数值:0,
来宾:[]},
{联系人ID:43766365,
displayName:'bbb,ccc',
数值:1,
宾馆:
['https://']},
{联系人ID:43766359,
显示名称:“ccc,ddd”,
数值:2,
宾馆:
['https://',
'https://]}]
*/
//扩展来宾URL证明是有问题的-请参阅下面的expandGuests函数
registrations=registrations.map(扩展来宾);
控制台日志(注册);
/*注册只是等待承诺,而不是真正的数据
[承诺{},
承诺{},
承诺{}]
*/
返回{
状态代码:200,
标题:{
“访问控制允许来源”:“*”,
},
正文:JSON.stringify(注册),
};
}
捕获(例外){
console.log(异常);
返回{
状态代码:500,
正文:“无法检索数据。”
};
}
};
函数getEventRegistrations(){
返回获取(“”)
.then(res=>res.json())
.catch(函数(错误){
console.log('事件注册者请求失败',错误);
返回null;
});
}
函数getGuestName(url){
返回获取(url)
.then(res=>res.json())
.then(guest=>guest.DisplayName)
.catch(函数(错误){
console.log('Guest name request failed',error);
返回null;
});
}
异步函数(数据){
const promises=data.guestUrls.map(url=>getGuestName(url));
data.guestNames=等待承诺.all(承诺);
返回数据;
}
我如何解决这些未决的承诺,从而返回有用的数据


谢谢。

array.map不包含任何等待承诺的逻辑。它只是为数组的每个元素调用函数,然后同步生成一个结果数组。如果传入异步函数,那么结果将是一个承诺数组(因为所有异步函数都返回承诺)

您需要使用
Promise.all
创建一个承诺,该承诺将在所有单个承诺解决后解决,然后
等待解决

const promises = data.guestUrls.map(url => getGuestName(url));
data.guestNames = await Promise.all(promises);

另外,我强烈建议不要将async/await与.then混合使用。实际需要这样做的情况非常罕见,因此大多数情况下,您只是使代码更难理解。例如,此功能:

async function getGuestName(url) {
    return await fetch(url)
    .then(res => res.json())
    .then(guest => guest.DisplayName)
    .catch(function (error) {
        console.log('Guest name request failed', error);
        return null;
    });
}
应该这样做:

async function getGuestName(url) {
  try {
    const res = await fetch(url);
    const guest = await res.json();
    return guest.DisplayName;
  } catch (error) {
    console.log('Guest name request failed', error);
    return null;
  }
}
还是像这样

 function getGuestName(url) {
    return fetch(url)
    .then(res => res.json())
    .then(guest => guest.DisplayName)
    .catch(function (error) {
        console.log('Guest name request failed', error);
        return null;
    });
}



注释正确地指出映射
async
函数将返回一个承诺数组。他们没有明确提到的是,你有两个地图,哪一个是有问题的

问题在于:

reservations = reservations.map(expandGuests);
无论何时使用map,您都需要实际解决返回的承诺

因此:


你不能。承诺是有感染力的。如果函数使用它们,则使用该函数的每个函数都必须使用它们。这就是异步代码在is中的工作方式。每个
async
函数都返回一个承诺。他们就是这样工作的。因此,您必须在
async
函数调用中使用
.then()
wait
,以获取其最终解析值。感谢您的快速回复。将
expandGuests
函数更改为:`async function expandGuests(data){const promises=data.guestUrls.map(url=>getGuestName(url));data.guestNames=wait Promise.all(promises);return data;}`导致输出“[Promise{},Promise{},Promise{}]”(从
console.log)(注册)
registrations=registrations.map(expandGuests);
)再次感谢@nicholas tower。额外的“ps”点也非常有用,现在已经实施。是的!谢谢。这解决了问题。很明显,其他答案现在是准确的,但只有这一洞察最终在正确的地方发出了光芒。
const mappedPromises = reservations.map(expandGuests);  //returns an Array of Pending promises
const mappedReservations = await Promise.all(mappedPromises);  //resolves the promises