mirror of https://github.com/vector-im/riot-web
Replace bluebird specific promise things. Fix uses of sync promise code.
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>pull/21833/head
parent
5c24547ef5
commit
54dcaf1302
|
@ -21,6 +21,7 @@ import MultiInviter from './utils/MultiInviter';
|
||||||
import { _t } from './languageHandler';
|
import { _t } from './languageHandler';
|
||||||
import MatrixClientPeg from './MatrixClientPeg';
|
import MatrixClientPeg from './MatrixClientPeg';
|
||||||
import GroupStore from './stores/GroupStore';
|
import GroupStore from './stores/GroupStore';
|
||||||
|
import {allSettled} from "./utils/promise";
|
||||||
|
|
||||||
export function showGroupInviteDialog(groupId) {
|
export function showGroupInviteDialog(groupId) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -118,7 +119,7 @@ function _onGroupInviteFinished(groupId, addrs) {
|
||||||
function _onGroupAddRoomFinished(groupId, addrs, addRoomsPublicly) {
|
function _onGroupAddRoomFinished(groupId, addrs, addRoomsPublicly) {
|
||||||
const matrixClient = MatrixClientPeg.get();
|
const matrixClient = MatrixClientPeg.get();
|
||||||
const errorList = [];
|
const errorList = [];
|
||||||
return Promise.all(addrs.map((addr) => {
|
return allSettled(addrs.map((addr) => {
|
||||||
return GroupStore
|
return GroupStore
|
||||||
.addRoomToGroup(groupId, addr.address, addRoomsPublicly)
|
.addRoomToGroup(groupId, addr.address, addRoomsPublicly)
|
||||||
.catch(() => { errorList.push(addr.address); })
|
.catch(() => { errorList.push(addr.address); })
|
||||||
|
@ -138,7 +139,7 @@ function _onGroupAddRoomFinished(groupId, addrs, addRoomsPublicly) {
|
||||||
groups.push(groupId);
|
groups.push(groupId);
|
||||||
return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.related_groups', {groups}, '');
|
return MatrixClientPeg.get().sendStateEvent(roomId, 'm.room.related_groups', {groups}, '');
|
||||||
}
|
}
|
||||||
}).reflect();
|
});
|
||||||
})).then(() => {
|
})).then(() => {
|
||||||
if (errorList.length === 0) {
|
if (errorList.length === 0) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -27,6 +27,7 @@ import UserProvider from './UserProvider';
|
||||||
import EmojiProvider from './EmojiProvider';
|
import EmojiProvider from './EmojiProvider';
|
||||||
import NotifProvider from './NotifProvider';
|
import NotifProvider from './NotifProvider';
|
||||||
import Promise from 'bluebird';
|
import Promise from 'bluebird';
|
||||||
|
import {timeout} from "../utils/promise";
|
||||||
|
|
||||||
export type SelectionRange = {
|
export type SelectionRange = {
|
||||||
beginning: boolean, // whether the selection is in the first block of the editor or not
|
beginning: boolean, // whether the selection is in the first block of the editor or not
|
||||||
|
@ -77,23 +78,16 @@ export default class Autocompleter {
|
||||||
while the user is interacting with the list, which makes it difficult
|
while the user is interacting with the list, which makes it difficult
|
||||||
to predict whether an action will actually do what is intended
|
to predict whether an action will actually do what is intended
|
||||||
*/
|
*/
|
||||||
const completionsList = await Promise.all(
|
const completionsList = await Promise.all(this.providers.map(provider => {
|
||||||
// Array of inspections of promises that might timeout. Instead of allowing a
|
return timeout(provider.getCompletions(query, selection, force), null, PROVIDER_COMPLETION_TIMEOUT);
|
||||||
// single timeout to reject the Promise.all, reflect each one and once they've all
|
}));
|
||||||
// settled, filter for the fulfilled ones
|
|
||||||
this.providers.map(provider =>
|
// map then filter to maintain the index for the map-operation, for this.providers to line up
|
||||||
provider
|
return completionsList.map((completions, i) => {
|
||||||
.getCompletions(query, selection, force)
|
if (!completions || !completions.length) return;
|
||||||
.timeout(PROVIDER_COMPLETION_TIMEOUT)
|
|
||||||
.reflect(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return completionsList.filter(
|
|
||||||
(inspection) => inspection.isFulfilled(),
|
|
||||||
).map((completionsState, i) => {
|
|
||||||
return {
|
return {
|
||||||
completions: completionsState.value(),
|
completions,
|
||||||
provider: this.providers[i],
|
provider: this.providers[i],
|
||||||
|
|
||||||
/* the currently matched "command" the completer tried to complete
|
/* the currently matched "command" the completer tried to complete
|
||||||
|
@ -102,6 +96,6 @@ export default class Autocompleter {
|
||||||
*/
|
*/
|
||||||
command: this.providers[i].getCurrentCommand(query, selection, force),
|
command: this.providers[i].getCurrentCommand(query, selection, force),
|
||||||
};
|
};
|
||||||
});
|
}).filter(Boolean);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ import FlairStore from '../../stores/FlairStore';
|
||||||
import { showGroupAddRoomDialog } from '../../GroupAddressPicker';
|
import { showGroupAddRoomDialog } from '../../GroupAddressPicker';
|
||||||
import {makeGroupPermalink, makeUserPermalink} from "../../utils/permalinks/Permalinks";
|
import {makeGroupPermalink, makeUserPermalink} from "../../utils/permalinks/Permalinks";
|
||||||
import {Group} from "matrix-js-sdk";
|
import {Group} from "matrix-js-sdk";
|
||||||
import {sleep} from "../../utils/promise";
|
import {allSettled, sleep} from "../../utils/promise";
|
||||||
|
|
||||||
const LONG_DESC_PLACEHOLDER = _td(
|
const LONG_DESC_PLACEHOLDER = _td(
|
||||||
`<h1>HTML for your community's page</h1>
|
`<h1>HTML for your community's page</h1>
|
||||||
|
@ -99,11 +99,10 @@ const CategoryRoomList = createReactClass({
|
||||||
onFinished: (success, addrs) => {
|
onFinished: (success, addrs) => {
|
||||||
if (!success) return;
|
if (!success) return;
|
||||||
const errorList = [];
|
const errorList = [];
|
||||||
Promise.all(addrs.map((addr) => {
|
allSettled(addrs.map((addr) => {
|
||||||
return GroupStore
|
return GroupStore
|
||||||
.addRoomToGroupSummary(this.props.groupId, addr.address)
|
.addRoomToGroupSummary(this.props.groupId, addr.address)
|
||||||
.catch(() => { errorList.push(addr.address); })
|
.catch(() => { errorList.push(addr.address); });
|
||||||
.reflect();
|
|
||||||
})).then(() => {
|
})).then(() => {
|
||||||
if (errorList.length === 0) {
|
if (errorList.length === 0) {
|
||||||
return;
|
return;
|
||||||
|
@ -276,11 +275,10 @@ const RoleUserList = createReactClass({
|
||||||
onFinished: (success, addrs) => {
|
onFinished: (success, addrs) => {
|
||||||
if (!success) return;
|
if (!success) return;
|
||||||
const errorList = [];
|
const errorList = [];
|
||||||
Promise.all(addrs.map((addr) => {
|
allSettled(addrs.map((addr) => {
|
||||||
return GroupStore
|
return GroupStore
|
||||||
.addUserToGroupSummary(addr.address)
|
.addUserToGroupSummary(addr.address)
|
||||||
.catch(() => { errorList.push(addr.address); })
|
.catch(() => { errorList.push(addr.address); });
|
||||||
.reflect();
|
|
||||||
})).then(() => {
|
})).then(() => {
|
||||||
if (errorList.length === 0) {
|
if (errorList.length === 0) {
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1064,8 +1064,6 @@ const TimelinePanel = createReactClass({
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
let prom = this._timelineWindow.load(eventId, INITIAL_SIZE);
|
|
||||||
|
|
||||||
// if we already have the event in question, TimelineWindow.load
|
// if we already have the event in question, TimelineWindow.load
|
||||||
// returns a resolved promise.
|
// returns a resolved promise.
|
||||||
//
|
//
|
||||||
|
@ -1074,9 +1072,13 @@ const TimelinePanel = createReactClass({
|
||||||
// quite slow. So we detect that situation and shortcut straight to
|
// quite slow. So we detect that situation and shortcut straight to
|
||||||
// calling _reloadEvents and updating the state.
|
// calling _reloadEvents and updating the state.
|
||||||
|
|
||||||
if (prom.isFulfilled()) {
|
const timeline = this.props.timelineSet.getTimelineForEvent(eventId);
|
||||||
|
if (timeline) {
|
||||||
|
// This is a hot-path optimization by skipping a promise tick
|
||||||
|
// by repeating a no-op sync branch in TimelineSet.getTimelineForEvent & MatrixClient.getEventTimeline
|
||||||
onLoaded();
|
onLoaded();
|
||||||
} else {
|
} else {
|
||||||
|
const prom = this._timelineWindow.load(eventId, INITIAL_SIZE);
|
||||||
this.setState({
|
this.setState({
|
||||||
events: [],
|
events: [],
|
||||||
liveEvents: [],
|
liveEvents: [],
|
||||||
|
@ -1084,11 +1086,8 @@ const TimelinePanel = createReactClass({
|
||||||
canForwardPaginate: false,
|
canForwardPaginate: false,
|
||||||
timelineLoading: true,
|
timelineLoading: true,
|
||||||
});
|
});
|
||||||
|
prom.then(onLoaded, onError);
|
||||||
prom = prom.then(onLoaded, onError);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prom.done();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// handle the completion of a timeline load or localEchoUpdate, by
|
// handle the completion of a timeline load or localEchoUpdate, by
|
||||||
|
|
|
@ -136,6 +136,8 @@ class IndexedDBLogStore {
|
||||||
this.id = "instance-" + Math.random() + Date.now();
|
this.id = "instance-" + Math.random() + Date.now();
|
||||||
this.index = 0;
|
this.index = 0;
|
||||||
this.db = null;
|
this.db = null;
|
||||||
|
|
||||||
|
// these promises are cleared as soon as fulfilled
|
||||||
this.flushPromise = null;
|
this.flushPromise = null;
|
||||||
// set if flush() is called whilst one is ongoing
|
// set if flush() is called whilst one is ongoing
|
||||||
this.flushAgainPromise = null;
|
this.flushAgainPromise = null;
|
||||||
|
@ -208,15 +210,15 @@ class IndexedDBLogStore {
|
||||||
*/
|
*/
|
||||||
flush() {
|
flush() {
|
||||||
// check if a flush() operation is ongoing
|
// check if a flush() operation is ongoing
|
||||||
if (this.flushPromise && this.flushPromise.isPending()) {
|
if (this.flushPromise) {
|
||||||
if (this.flushAgainPromise && this.flushAgainPromise.isPending()) {
|
if (this.flushAgainPromise) {
|
||||||
// this is the 3rd+ time we've called flush() : return the same
|
// this is the 3rd+ time we've called flush() : return the same promise.
|
||||||
// promise.
|
|
||||||
return this.flushAgainPromise;
|
return this.flushAgainPromise;
|
||||||
}
|
}
|
||||||
// queue up a flush to occur immediately after the pending one
|
// queue up a flush to occur immediately after the pending one completes.
|
||||||
// completes.
|
|
||||||
this.flushAgainPromise = this.flushPromise.then(() => {
|
this.flushAgainPromise = this.flushPromise.then(() => {
|
||||||
|
// clear this.flushAgainPromise
|
||||||
|
this.flushAgainPromise = null;
|
||||||
return this.flush();
|
return this.flush();
|
||||||
});
|
});
|
||||||
return this.flushAgainPromise;
|
return this.flushAgainPromise;
|
||||||
|
@ -232,12 +234,16 @@ class IndexedDBLogStore {
|
||||||
}
|
}
|
||||||
const lines = this.logger.flush();
|
const lines = this.logger.flush();
|
||||||
if (lines.length === 0) {
|
if (lines.length === 0) {
|
||||||
|
// clear this.flushPromise
|
||||||
|
this.flushPromise = null;
|
||||||
resolve();
|
resolve();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const txn = this.db.transaction(["logs", "logslastmod"], "readwrite");
|
const txn = this.db.transaction(["logs", "logslastmod"], "readwrite");
|
||||||
const objStore = txn.objectStore("logs");
|
const objStore = txn.objectStore("logs");
|
||||||
txn.oncomplete = (event) => {
|
txn.oncomplete = (event) => {
|
||||||
|
// clear this.flushPromise
|
||||||
|
this.flushPromise = null;
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
txn.onerror = (event) => {
|
txn.onerror = (event) => {
|
||||||
|
|
|
@ -47,3 +47,20 @@ export function defer(): {resolve: () => {}, reject: () => {}, promise: Promise}
|
||||||
|
|
||||||
return {resolve, reject, promise};
|
return {resolve, reject, promise};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Promise.allSettled polyfill until browser support is stable in Firefox
|
||||||
|
export function allSettled(promises: Promise[]): {status: string, value?: any, reason?: any}[] {
|
||||||
|
if (Promise.allSettled) {
|
||||||
|
return Promise.allSettled(promises);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Promise.all(promises.map((promise) => {
|
||||||
|
return promise.then(value => ({
|
||||||
|
status: "fulfilled",
|
||||||
|
value,
|
||||||
|
})).catch(reason => ({
|
||||||
|
status: "rejected",
|
||||||
|
reason,
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue