【问题标题】:Am I using Promise.all() incorrectly?我是否错误地使用了 Promise.all()?
【发布时间】:2021-07-27 04:45:49
【问题描述】:


Code Here
我正在尝试遍历返回响应的迭代,以根据需要准确描述信息。


目前,CaseContactName 和 CaseSiteName 来自不同的 API 调用,然后将数据附加到图表上,但是在当前状态下,响应并未与所有与表数据相关的内容同步这些值通过模型关系绑定。


我希望正确附加联系人姓名和站点名称,我尝试了 3 种不同的循环方法,它要么附加名字/联系人,要么根本不附加。这是一个烦人的数据,有人建议我使用 Promise.All 功能,因为它用于刺激的情况,但我觉得我好像迷路了。
代码如下

       const callRmaCases = async () => {
        //    $tbody.empty(); 
             axios.get('/api/Case').then((response) => {
                for(let i = 0; response.data.length > 0; i++){
                    const caseContactName = Promise.resolve(response.data[i].Contact.name);
                    const caseSiteName = Promise.resolve(response.data[i].Site.siteName);
                     console.log(response);
                     console.log(caseContactName, caseSiteName)
                     
                     Promise.all([caseContactName,caseSiteName]).then((values) => {
                        console.log(values);
                        callRmaInvent([caseContactName,caseSiteName])  
                     });
                };
            }).catch((err) => {
                console.log(err);
            })
            
            };

        const callRmaInvent = async (caseContactName, caseSiteName) => {

        await(caseSiteName, caseContactName);
     axios.get('/api/caseDetail').then((items) => {
        $tbody.empty();
        console.log(items);
        console.log('inventory will go here');
       items.data.forEach((item) => {
            const id = item.id;
            // Table data
            const caseName = item.Case.caseName;
            const caseSite =  caseSiteName;
            const caseContact =  caseContactName;
            const itemType = item.Part.partType;
            const serialNumber = item.Part.serialNumber;
            const createdAt = item.createdAt;
            const updatedAt = item.updatedAt;
            const faultReason = item.Fault.reasonForReturn;
            const dispositionAction = item.Disposition.actionTaken;
            const addedToInvent = dateFns.format(createdAt, 'MMM D, YY')
            const updatedInvent = dateFns.format(updatedAt, 'MMM D, YY')

            $tbody.append(`
            <tr>
            <td>${id}</td>
            <td>${caseName}</td>
            <td>${caseSite}</td>
            <td>${caseContact}</td>
            <td>${serialNumber}</td>
            <td>${itemType}</td>         
            <td>${faultReason}</td>
            <td>${dispositionAction}</td>
            <td>${addedToInvent}</td>
            <td>${updatedInvent}</td>
            </tr>`)
        });
    }).catch((err) => {
        console.log(err)
    });   
    };


你可以看到 Contact 在这里出现一次 undefined ,但是之后正确显示,我可能只是在这里真的很困惑,并试图使用错误的方法来达到我需要的结果。
控制台日志显示:

{data: Array(2), status: 200, statusText: "OK", headers: {…}, config: {…}, …}config: {url: "/api/Case", method: "get", headers: {…}, transformRequest: Array(1), transformResponse: Array(1), …}data: (2) [{…}, {…}]headers: {content-length: "1474", content-type: "application/json; charset=utf-8", date: "Mon, 26 Jul 2021 19:47:17 GMT", etag: "W/\"5c2-BNGcGEUTd4sqd6BxFY9mWpUJgeU\"", x-powered-by: "Express"}request: XMLHttpRequest {readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, onreadystatechange: ƒ, …}status: 200statusText: "OK"__proto__: Object
script.js:16 Promise {<fulfilled>: "Blake Thompson"}__proto__: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: "Blake Thompson" Promise {<fulfilled>: "Disney World"}
script.js:15 {data: Array(2), status: 200, statusText: "OK", headers: {…}, config: {…}, …}config: {url: "/api/Case", method: "get", headers: {…}, transformRequest: Array(1), transformResponse: Array(1), …}data: (2) [{…}, {…}]headers: {content-length: "1474", content-type: "application/json; charset=utf-8", date: "Mon, 26 Jul 2021 19:47:17 GMT", etag: "W/\"5c2-BNGcGEUTd4sqd6BxFY9mWpUJgeU\"", x-powered-by: "Express"}request: XMLHttpRequest {readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, onreadystatechange: ƒ, …}status: 200statusText: "OK"__proto__: Object
script.js:16 Promise {<fulfilled>: "Eric"}__proto__: Promise[[PromiseState]]: "fulfilled"[[PromiseResult]]: "Eric" Promise {<fulfilled>: "Warehouse"}
script.js:34 TypeError: Cannot read property 'Contact' of undefined
    at script.js:13
script.js:19 (2) ["Blake Thompson", "Disney World"]0: "Blake Thompson"1: "Disney World"length: 2__proto__: Array(0)
script.js:19 (2) ["Eric", "Warehouse"]

【问题讨论】:

  • 避免在异步方法中使用.then。
  • 你 console.log(values);,然后你继续将 [caseContactName,caseSiteName] 传递给 callRmaInvent() 这是两个承诺。不要那样做,使用values。
  • await(caseSiteName, caseContactName); 没有按照您的预期行事。
  • "我是否错误地使用了 Promise.all()?" - 是的,绝对的。你应该从不做出 caseContactName 和 caseSiteName 承诺开始 - 没有充分的理由 Promise.resolve 他们!
  • @Bergi 语法示例显示 Promise.resolve 作为使用 Promise.All() 的要求,这就是在这种情况下使用它们的原因。欣赏洞察力。

标签: javascript node.js arrays promise sequelize.js


【解决方案1】:

是的,你的所作所为毫无意义。

const caseContactName = Promise.resolve(response.data[i].Contact.name);
const caseSiteName = Promise.resolve(response.data[i].Site.siteName);
                     
Promise.all([caseContactName,caseSiteName]).then((values) => {
  callRmaInvent(caseContactName, caseSiteName)  
});

在此代码示例中,您将 2 个 Promise 传递给 Promise.all()。 then 处理程序将获得这 2 个 promise 的 result,但是您没有将结果传递给 callRmaInvent,而是传递了原始 promise。

所以,你会想要这个:

const caseContactName = Promise.resolve(response.data[i].Contact.name);
const caseSiteName = Promise.resolve(response.data[i].Site.siteName);
                     
Promise.all([caseContactName,caseSiteName]).then((values) => {
  callRmaInvent(values[0], values[1])  
});

但是,这里不需要使用Promise.resolve(),因为您已经有了数据,因此可以进一步缩短为:

const caseContactName = response.data[i].Contact.name;
const caseSiteName = response.data[i].Site.siteName;
                     
callRmaInvent(caseContactName, caseSiteName)  

整个外部方法可以简化为:

const callRmaCases = async () => {
 
  //    $tbody.empty(); 
  const response = await axios.get('/api/Case');
  for(const item of response.data) {
     const caseContactName = item.Contact.name;
     const caseSiteName = item.Site.siteName;

     callRmaInvent(caseContactName, caseSiteName);
  }
}

【讨论】:

  • 请注意,即使 caseContactName 和 caseSiteName 是承诺,您也可以这样做:callRmaInvent(...await Promise.all([ caseContactName, caseSiteName ]));
  • 我被从办公桌上拉了下来,所以我在手机上看到了这个,非常感谢您在回复中投入的时间。有几个使用 promise.All 时的语法示例,当我在之前的线程中询问我正在处理的情况时,我被指出 here 我会尽快回到这个问题。
  • @Gershy 我会试一试,感谢您的宝贵时间!
【解决方案2】:

你把我猜想的一切都搞砸了。我已经重写了您的代码的更简单版本。可能需要根据服务器的响应进行一些更改。

const callRmaCases = async () => {
try {
    const response = await axios.get('/api/Case')
    // assuming you are getting a json object
    const responseData = await response.json()
    responseData.forEach(innerObject => {
        callRmaInvent(innerObject.Contact.name, innerObject.Site.siteName)  
    })
} catch(error) {
    console.table(error.name, error.type, error.stack)
}  
};

const callRmaInvent = async (caseContactName, caseSiteName) => {
try {
    const items = await axios.get('/api/caseDetail')
    $tbody.empty();
    items.data.forEach((item) => {
            $tbody.append(`
            <tr>
            <td>${item.id}</td>
            <td>${item.Case.caseName}</td>
            <td>${caseSiteName}</td>
            <td>${item.Part.partType}</td>
            <td>${item.Part.serialNumber}</td>
            <td>${item.Part.partType}</td>         
            <td>${item.Fault.reasonForReturn}</td>
            <td>${item.Disposition.actionTaken}</td>
            <td>${dateFns.format(createdAt, 'MMM D, YY')}</td>
            <td>${dateFns.format(updatedAt, 'MMM D, YY')}</td>
            </tr>`)
    });   
} catch(error) {
    console.table([error.name, error.type, error.stack])
}   
};

可以通过多种方式处理未解决的承诺。我喜欢异步等待。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多