0

Проблема возникает из-за того, что получение данных из бд происходит медленно, без async\await получается, что чтение из бд слишком медленное.

В componentWillMount() вылезает ошибка Cannot read property 'find' of undefined, потому что getfieldsets() не успевает отработать к этому времени (как я понимаю)

async function fieldsetsWork(){
    //объявление переменных
    var k=0;
    var string = '';
    var def = getFields().map((it,i)=>({
            name:it.name,
            hidden: false,}));
    var stringDef ='';
    for (var i=0;i<def.length;i++){
        stringDef = stringDef + def[i].name;
    }
    // проверка на существование филдсетов пользователя
    var pushDbUser = Dexie.async(function* (){
        try {
            var p = yield db.table('fieldsets').each(function(element){
                if (element.f_Uname.includes(global.currentUser.value.login.toString())){
                    fieldsets_.push(element);
                    k++;
                }});
            yield p;
            yield console.log('null',fieldsets_);
            yield console.log(fieldsets_[0]);
        } finally { return 0; }
    })

    await pushDbUser().catch(e => console.error(e));


    // проверка версии
    if (k !== 0){
        for (var i=0;i<fieldsets_[0].data.length;i++){
        string = string +fieldsets_[0].data[i].name; }
        if (string == stringDef){ k = k;
        }else k = 0;
    }; 
    await console.log(k);
    // если нет филдсетов добавляем дефолтные
    var pushFDB = Dexie.async(function* (){
        try {
            var p = yield db.table('fieldsets').each(element =>{
            console.log(element)
                if (element.f_Uname.includes('default')){
                fieldsets_.push(element);
                console.log(element);
            }})
            yield p;
            yield console.log('null2',fieldsets_);
            yield console.log(fieldsets_[0]);
            yield console.log('0');
        } finally { return 0; }
    })
    if (k===0){
        await console.log('k=0')
        await pushFDB().catch(e => console.error(e));
        }
    await localStorage.setItem('requirements_fieldsets', JSON.stringify(fieldsets_))
    var p = await fieldsets_.forEach(fieldset=>
        fieldset.data.forEach(field=> field.def = getFields().find(it=> it.name===field.name)));
    fieldsets =  p;
     return  fieldsets_;
}
fieldsetsWork();


export function getFieldsets(force){
    if(force){
        const fieldsets_ = fieldsetsWork(); //JSON.parse(localStorage.getItem('requirements_fieldsets'));
        fieldsets_.forEach(fieldset=>
            fieldset.data.forEach(field=> field.def = getFields().find(it=> it.name===field.name)));
        fieldsets = fieldsets_
    }
    return fieldsets
}



componentWillMount(){
        this.setState(old=>({
            ...old,
            fieldset: getFieldsets().find(it=>it.favourite)
        }));
    }

1 Answers1

1

У вас есть два варианта, при данной структуре организации кода.

Вызвать await fieldsetsWork(). Тогда остальная часть кода не будет выполняться, будет ожидать. На самом деле не очень хороший вариант.

async function fieldsetsWork(){
    //объявление переменных
    var k=0;
    var string = '';
    var def = getFields().map((it,i)=>({
            name:it.name,
            hidden: false,}));
    var stringDef ='';
    for (var i=0;i<def.length;i++){
        stringDef = stringDef + def[i].name;
    }
    // проверка на существование филдсетов пользователя
    var pushDbUser = Dexie.async(function* (){
        try {
            var p = yield db.table('fieldsets').each(function(element){
                if (element.f_Uname.includes(global.currentUser.value.login.toString())){
                    fieldsets_.push(element);
                    k++;
                }});
            yield p;
            yield console.log('null',fieldsets_);
            yield console.log(fieldsets_[0]);
        } finally { return 0; }
    })

    await pushDbUser().catch(e => console.error(e));


    // проверка версии
    if (k !== 0){
        for (var i=0;i<fieldsets_[0].data.length;i++){
        string = string +fieldsets_[0].data[i].name; }
        if (string == stringDef){ k = k;
        }else k = 0;
    }; 
    await console.log(k);
    // если нет филдсетов добавляем дефолтные
    var pushFDB = Dexie.async(function* (){
        try {
            var p = yield db.table('fieldsets').each(element =>{
            console.log(element)
                if (element.f_Uname.includes('default')){
                fieldsets_.push(element);
                console.log(element);
            }})
            yield p;
            yield console.log('null2',fieldsets_);
            yield console.log(fieldsets_[0]);
            yield console.log('0');
        } finally { return 0; }
    })
    if (k===0){
        await console.log('k=0')
        await pushFDB().catch(e => console.error(e));
        }
    await localStorage.setItem('requirements_fieldsets', JSON.stringify(fieldsets_))
    var p = await fieldsets_.forEach(fieldset=>
        fieldset.data.forEach(field=> field.def = getFields().find(it=> it.name===field.name)));
    fieldsets =  p;
     return  fieldsets_;
}
await fieldsetsWork();


export function getFieldsets(force){
    if(force){
        const fieldsets_ = fieldsetsWork(); //JSON.parse(localStorage.getItem('requirements_fieldsets'));
        fieldsets_.forEach(fieldset=>
            fieldset.data.forEach(field=> field.def = getFields().find(it=> it.name===field.name)));
        fieldsets = fieldsets_
    }
    return fieldsets
}



componentWillMount(){
        this.setState(old=>({
            ...old,
            fieldset: getFieldsets().find(it=>it.favourite)
        }));
    } 

Есть другой вариант, получше. Не вызывать отдельно fieldsetsWork, а запустить getFieldsets с параметром force=true. Также переделать fieldsetsWork на асинхронную.

async function fieldsetsWork(){
    //объявление переменных
    var k=0;
    var string = '';
    var def = getFields().map((it,i)=>({
            name:it.name,
            hidden: false,}));
    var stringDef ='';
    for (var i=0;i<def.length;i++){
        stringDef = stringDef + def[i].name;
    }
    // проверка на существование филдсетов пользователя
    var pushDbUser = Dexie.async(function* (){
        try {
            var p = yield db.table('fieldsets').each(function(element){
                if (element.f_Uname.includes(global.currentUser.value.login.toString())){
                    fieldsets_.push(element);
                    k++;
                }});
            yield p;
            yield console.log('null',fieldsets_);
            yield console.log(fieldsets_[0]);
        } finally { return 0; }
    })

    await pushDbUser().catch(e => console.error(e));


    // проверка версии
    if (k !== 0){
        for (var i=0;i<fieldsets_[0].data.length;i++){
        string = string +fieldsets_[0].data[i].name; }
        if (string == stringDef){ k = k;
        }else k = 0;
    }; 
    await console.log(k);
    // если нет филдсетов добавляем дефолтные
    var pushFDB = Dexie.async(function* (){
        try {
            var p = yield db.table('fieldsets').each(element =>{
            console.log(element)
                if (element.f_Uname.includes('default')){
                fieldsets_.push(element);
                console.log(element);
            }})
            yield p;
            yield console.log('null2',fieldsets_);
            yield console.log(fieldsets_[0]);
            yield console.log('0');
        } finally { return 0; }
    })
    if (k===0){
        await console.log('k=0')
        await pushFDB().catch(e => console.error(e));
        }
    await localStorage.setItem('requirements_fieldsets', JSON.stringify(fieldsets_))
    var p = await fieldsets_.forEach(fieldset=>
        fieldset.data.forEach(field=> field.def = getFields().find(it=> it.name===field.name)));
    fieldsets =  p;
     return  fieldsets_;
}
fieldsetsWork();


export async function getFieldsets(force){
    if(force){
        const fieldsets_ = await fieldsetsWork(); //JSON.parse(localStorage.getItem('requirements_fieldsets'));
        fieldsets_.forEach(fieldset=>
            fieldset.data.forEach(field=> field.def = getFields().find(it=> it.name===field.name)));
        fieldsets = fieldsets_
    }
    return fieldsets
}



componentWillMount(){
        this.setState(old=>({
            ...old,
            fieldset: await getFieldsets(true).find(it=>it.favourite)
        }));
    }
  • в первом случае await fieldsetsWork() выдаёт ошибку, надо что-то импортить дополнительно, чтобы await работал?

    второй случай проверяю

    – Ivan Burilichev Dec 24 '18 at 07:04
  • @IvanBurilichev Так вы же await уже везде используете. Или не вы этот код писали? – Stepan Kasyanenko Dec 24 '18 at 07:25
  • частично я, но await не везде используется, то есть такой await, который предлагаете написать вы, будет лежать в компоненте, а не в функции – Ivan Burilichev Dec 24 '18 at 07:31
  • @IvanBurilichev И в чем проблема? Вы приведенные примеры пробовали? – Stepan Kasyanenko Dec 24 '18 at 07:57
  • В случае await fieldsetsWork() выдаёт Parsing error: await is a reserved word А во втором случае, когда await рядом с getFieldsets().find(it=>it.favourite) тоже выдаёт Parsing error: await is a reserved word

    Если убрать из componentWillMount() await, то просто выдаёт Object(...)(...).find is not a function

    – Ivan Burilichev Dec 24 '18 at 08:59
  • @IvanBurilichev в таком случае показывайте полный пример. – Stepan Kasyanenko Dec 24 '18 at 10:26