mirror of
https://github.com/sveltejs/svelte.git
synced 2024-12-01 17:30:59 +01:00
Merge pull request #1882 from sveltejs/glitch-free
Glitch free reactive stores
This commit is contained in:
commit
b40c15349c
46
store.js
46
store.js
@ -1,4 +1,4 @@
|
||||
import { run_all } from './internal.js';
|
||||
import { run_all, noop } from './internal.js';
|
||||
|
||||
export function readable(start, value) {
|
||||
const subscribers = [];
|
||||
@ -7,20 +7,22 @@ export function readable(start, value) {
|
||||
function set(newValue) {
|
||||
if (newValue === value) return;
|
||||
value = newValue;
|
||||
subscribers.forEach(fn => fn(value));
|
||||
subscribers.forEach(s => s[1]());
|
||||
subscribers.forEach(s => s[0](value));
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe(fn) {
|
||||
subscribe(run, invalidate = noop) {
|
||||
if (subscribers.length === 0) {
|
||||
stop = start(set);
|
||||
}
|
||||
|
||||
subscribers.push(fn);
|
||||
fn(value);
|
||||
const subscriber = [run, invalidate];
|
||||
subscribers.push(subscriber);
|
||||
run(value);
|
||||
|
||||
return function() {
|
||||
const index = subscribers.indexOf(fn);
|
||||
const index = subscribers.indexOf(subscriber);
|
||||
if (index !== -1) subscribers.splice(index, 1);
|
||||
|
||||
if (subscribers.length === 0) {
|
||||
@ -38,19 +40,21 @@ export function writable(value) {
|
||||
function set(newValue) {
|
||||
if (newValue === value) return;
|
||||
value = newValue;
|
||||
subscribers.forEach(fn => fn(value));
|
||||
subscribers.forEach(s => s[1]());
|
||||
subscribers.forEach(s => s[0](value));
|
||||
}
|
||||
|
||||
function update(fn) {
|
||||
set(fn(value));
|
||||
}
|
||||
|
||||
function subscribe(fn) {
|
||||
subscribers.push(fn);
|
||||
fn(value);
|
||||
function subscribe(run, invalidate = noop) {
|
||||
const subscriber = [run, invalidate];
|
||||
subscribers.push(subscriber);
|
||||
run(value);
|
||||
|
||||
return () => {
|
||||
const index = subscribers.indexOf(fn);
|
||||
const index = subscribers.indexOf(subscriber);
|
||||
if (index !== -1) subscribers.splice(index, 1);
|
||||
};
|
||||
}
|
||||
@ -63,20 +67,30 @@ export function derive(stores, fn) {
|
||||
if (single) stores = [stores];
|
||||
|
||||
const auto = fn.length === 1;
|
||||
let value = {};
|
||||
|
||||
return readable(set => {
|
||||
let inited = false;
|
||||
const values = [];
|
||||
|
||||
let pending = 0;
|
||||
|
||||
const sync = () => {
|
||||
if (pending) return;
|
||||
const result = fn(single ? values[0] : values, set);
|
||||
if (auto) set(result);
|
||||
if (auto && (value !== (value = result))) set(result);
|
||||
}
|
||||
|
||||
const unsubscribers = stores.map((store, i) => store.subscribe(value => {
|
||||
values[i] = value;
|
||||
if (inited) sync();
|
||||
}));
|
||||
const unsubscribers = stores.map((store, i) => store.subscribe(
|
||||
value => {
|
||||
values[i] = value;
|
||||
pending &= ~(1 << i);
|
||||
if (inited) sync();
|
||||
},
|
||||
() => {
|
||||
pending |= (1 << i);
|
||||
})
|
||||
);
|
||||
|
||||
inited = true;
|
||||
sync();
|
||||
|
@ -128,5 +128,27 @@ describe('store', () => {
|
||||
number.set(7);
|
||||
assert.deepEqual(values, [0, 2, 4]);
|
||||
});
|
||||
|
||||
it('prevents glitches', () => {
|
||||
const lastname = writable('Jekyll');
|
||||
const firstname = derive(lastname, n => n === 'Jekyll' ? 'Henry' : 'Edward');
|
||||
|
||||
const fullname = derive([firstname, lastname], names => names.join(' '));
|
||||
|
||||
const values = [];
|
||||
|
||||
const unsubscribe = fullname.subscribe(value => {
|
||||
values.push(value);
|
||||
});
|
||||
|
||||
lastname.set('Hyde');
|
||||
|
||||
assert.deepEqual(values, [
|
||||
'Henry Jekyll',
|
||||
'Edward Hyde'
|
||||
]);
|
||||
|
||||
unsubscribe();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user