Richard Richard - 1 month ago 14
TypeScript Question

Javascript 'Promise' how to make Synchronous

I am using Ionic2/Typescript.

I have 2

Promise
's that I want to have complete, before I continue (i.e synchronous). So I put the call to the 2 functions in a
Promise.all(...)
, expecting them to complete before
resolve
is called.

I have the following code:

public openDatabase(): Promise<Array<Message>> {
let promise: Promise<Array<Message>> = new Promise<Array<Message>>(resolve => {
if (false && this.database && this.database != null) {
Promise.all([this.refreshChats(this.database), this.refreshMessages(this.database)]).then(() => {
console.log('openDatabase1: resolve');
resolve(this.messages);
});
} else {
this.database = new SQLite();
this.database.openDatabase({
name: "data.db",
location: "default"
}).then(() => {
Promise.all([this.refreshChats(this.database), this.refreshMessages(this.database)]).then(() => {
console.log('openDatabase2: resolve');
resolve(this.messages);
});
}, (error) => {
console.log("OPEN ERROR: ", error);
});
}
});
return promise;
}

public refreshChats(db: any): Promise<any> {
console.log('refreshChats ');
return db.executeSql("SELECT * FROM chats", [])
.then((chatData) => {
let promises: Array<any> = [];
this.chats = [];
if (chatData.rows.length > 0) {
for (var i = 0; i < chatData.rows.length; i++) {
promises.push(this.populateChat(db, chatData.rows.item(i)));
}
}
Promise.all(promises).then(() => {
console.log('refreshChats return this.chats.length = ' + this.chats.length);
return this.chats;
});
})
.catch(error => {
console.log("ERROR REFRESHING CHATS: " + JSON.stringify(error));
console.log(error);
});
}


From my console output, you can see that
resolve
is called before the chats are finished refreshing:


refreshChats
populateChat Object {...}
openDatabase2: resolve
refreshChats return this.chats.length = 1



Any advise on how I should structure my
Promises
is appreciated.

Answer

You need to return new promises from inner promise callbacks:

public openDatabase(): Promise<Array<Message>> {
    let promise: Promise<Array<Message>> = new Promise<Array<Message>>(resolve => {
        if (false && this.database && this.database != null) {
            return Promise.all([this.refreshChats(this.database), this.refreshMessages(this.database)]).then(() => {
                console.log('openDatabase1: resolve');
                resolve(this.messages);
            });
        } else {
            this.database = new SQLite();
            return this.database.openDatabase({
                name: "data.db",
                location: "default"
            }).then(() => {
                return Promise.all([this.refreshChats(this.database), this.refreshMessages(this.database)]).then(() => {
                    console.log('openDatabase2: resolve');
                    resolve(this.messages);
                });
            }, (error) => {
                console.log("OPEN ERROR: ", error);
            });
        }
    });
    return promise;
}

public refreshChats(db: any): Promise<any> {
    console.log('refreshChats ');
    return db.executeSql("SELECT * FROM chats", [])
        .then((chatData) => {
            let promises: Array<any> = [];
            this.chats = [];
            if (chatData.rows.length > 0) {
                for (var i = 0; i < chatData.rows.length; i++) {
                    promises.push(this.populateChat(db, chatData.rows.item(i)));
                }
            }
            return Promise.all(promises).then(() => {
                console.log('refreshChats return this.chats.length = ' + this.chats.length);
                return this.chats;
            });
        })
        .catch(error => {
            console.log("ERROR REFRESHING CHATS: " + JSON.stringify(error));
            console.log(error);
        });
}

Note, return Promise.all and return this.database.openDatabase.