通常登入帳戶後, context 不能被切換, 萬一執行非同步工作(async function)時, 有可能切換到其它帳戶, 造成 contex 大亂, 解決方式是實現一個 mutual exclusion 機制, 保護 context 順利進行:
// mutexLogin.js
class Guest {
constructor(id=0) { this.user = "anonymous" + id }
}
class Field {
constructor(value=false) { this.field = value }
set value(v) { this.field = v }
get value( ) { return this.field }
}
class Mutex extends Field {
constructor( ) { super(); this.full = false; }
get isLock ( ) { return this.value } // alias getter
get lock ( ) { this.value = true } // getter, to set field
get unlock ( ) { this.resolve && this.resolve(true) } // getter, to resolver with true
get waitUnlock( ) { // getter, to return null when full, or a promise if available.
if (this.full) return null;
this.full = true; // one promise only, to skip the others.
return new Promise( (fullfill, x) => { // a promise
this.resolve = (value) => { // to define resolver
this.full = false;
this.value = false;
fullfill(value) ; // to fullfill the promise
} // end of this.resolve
}); // end of Promise
} // end of waitUnlock
} // end of class Mutex
const mutex = new Mutex( );
async function anonymousLogin(id) {
if (mutex.isLock) {
const promise = mutex.waitUnlock;
if (promise == null) console.log(" -> skip contex for id=" + id);
else promise.then( (_) => {
console.log("Wait so long: "+_);
anonymousLogin(id); // function recursive to restart again
});
} else {
const guest = new Guest(id);
mutex.lock; // contex to protect
console.log(guest.user+":");
await doSomething(); // do some aync task
mutex.unlock; // end of contex
}
}
async function doSomething( ) { // async task
console.log("I am working ...");
console.log("Done");
}
for(i =0; i<10; i++) anonymousLogin(i);
執行 js mutexLogin.js 看結果:
anonymous0:
I am working ...
Done
-> skip contex for id=2
-> skip contex for id=3
-> skip contex for id=4
-> skip contex for id=5
-> skip contex for id=6
-> skip contex for id=7
-> skip contex for id=8
-> skip contex for id=9
Wait so long: true
anonymous1:
I am working ...
Done
沒有留言:
張貼留言