2016-12-20 9 views
12

,) async शामिल कुछ मुद्दों/.reduce (साथ इंतजार आ रही है तो जैसे:JavaScript श्रृंखला .reduce साथ async/इंतजार

const data = await bodies.reduce(async(accum, current, index) => { 
    const methodName = methods[index] 
    const method = this[methodName] 
    if (methodName == 'foo') { 
    current.cover = await this.store(current.cover, id) 
    console.log(current) 
    return { 
     ...accum, 
     ...current 
    } 
    } 
    return { 
    ...accum, 
    ...method(current.data) 
    } 
}, {}) 
console.log(data) 

data वस्तु से पहले this.store कम्प्लिट्स लॉग होता है ..

मुझे पता है कि आप Promise.all एसिंक लूप के साथ उपयोग कर सकते हैं, लेकिन क्या यह .reduce() पर लागू होता है?

उत्तर

21

समस्या यह है कि अपने संचायक मूल्यों वादे कर रहे हैं - वे async function रों की वापसी मान रहे हैं। अनुक्रमिक मूल्यांकन प्राप्त करने के लिए (और सभी लेकिन पिछले यात्रा सब पर प्रतीक्षा कर रहे थे करने के लिए), आप

const data = await array.reduce(async (accumP, current, index) => { 
    const accum = await accumP; 
    … 
}, Promise.resolve(…)); 

जिसके अनुसार, उपयोग करने के लिए के लिए async/await मैं सामान्य रूप में होगा use plain loops instead of array iteration methods की सलाह देते हैं की जरूरत है, वे अधिक performant कर रहे हैं और अक्सर सरल।

+1

आपकी सलाह के लिए धन्यवाद:

मैं भी मेरा एक पुस्तकालय का उल्लेख करना चाहते हैं, Awaity.js

आप सहजता से reduce जैसे कार्यों का उपयोग करने देता कौन सा, map & filter बुलाया async/await साथ । मुझे लगता है मैं क्या कर रहा था के लिए पाश के लिए सिर्फ एक सादे का उपयोग कर समाप्त हो गया है, और यह कोड का एक ही लाइनों, लेकिन कहीं पढ़ने में आसान था ... –

+0

'' reduce' की initialValue' एक 'वादा करने की आवश्यकता नहीं है हालांकि, ज्यादातर मामलों में यह इरादा स्पष्ट करेगा। – EECOLOR

+0

@EECOLOR हालांकि, यह होना चाहिए। मैं वास्तव में एक वादे में एक सादा मूल्य डालने के लिए 'प्रतीक्षा' नापसंद करता हूं – Bergi

1

आप अपना पूरा नक्शा लपेट/अपने स्वयं के Promise.resolve में iterator ब्लॉक को कम करने और पूरा करने के लिए उस पर इंतजार कर सकते हैं। मुद्दा यह है कि संचयक में परिणामस्वरूप डेटा/ऑब्जेक्ट नहीं होता है जिसे आप प्रत्येक पुनरावृत्ति पर अपेक्षा करते हैं। आंतरिक async के कारण/इंतजार है/वादा चेन, संचायक खुद को अभी तक संभावना है कि खुद को हल करने के लिए वास्तविक वादे (दुकान करने के लिए अपने कॉल करने से पहले एक इंतजार कीवर्ड का उपयोग आप जन्म दे सकता है जो विश्वास करने के बावजूद हो जाएगा कि यात्रा नहीं होगा वास्तव में जब तक कि कॉल पूरा करता है और संचायक अद्यतन किया जाता है लौटने।

हालांकि यह सबसे खूबसूरत समाधान नहीं है, एक ही विकल्प आपके पास के रूप में एक जाने ताकि आपके डेटा वस्तु चर क्षेत्र से बाहर ले जाने और इसे आवंटित करने के लिए है उचित बाध्यकारी और उत्परिवर्तन हो सकता है। फिर इस डेटा ऑब्जेक्ट को अपने इटरेटर के अंदर से एसिंक/प्रतीक्षा/वादा कॉल के रूप में अपडेट करें।

/* allow the result object to be initialized outside of scope 
    rather than trying to spread results into your accumulator on iterations, 
    else your results will not be maintained as expected within the 
    internal async/await/Promise chain. 
*/  
let data = {}; 

await Promise.resolve(bodies.reduce(async(accum, current, index) => { 
    const methodName = methods[index] 
    const method = this[methodName]; 
    if (methodName == 'foo') { 
    // note: this extra Promise.resolve may not be entirely necessary 
    const cover = await Promise.resolve(this.store(current.cover, id)); 
    current.cover = cover; 
    console.log(current); 
    data = { 
     ...data, 
     ...current, 
    }; 
    return data; 
    } 
    data = { 
    ...data, 
    ...method(current.data) 
    }; 
    return data; 
}, {}); 
console.log(data); 
0

मुझे बर्गी का जवाब पसंद है, मुझे लगता है कि यह जाने का सही तरीका है। अंत में

import reduce from 'awaity/reduce'; 

const posts = await reduce([1,2,3], async (posts, id) => { 
    const res = await fetch('/api/posts/' + id); 
    const post = res.json(); 

    return { 
    ...posts, 
    [id]: post 
    } 
}, {}) 

posts // { 1: { ... }, 2: { ... }, 3: { ... } }