Skip to content

Promise.PSD

David Fahlander edited this page Jul 29, 2014 · 47 revisions

Syntax

Dexie.Promise.newPSD (function () { // Create a PSD scope

    Dexie.Promise.PSD.promiseSpecificVariable = 3; // Put something in it.
    
    new Dexie.Promise(function (resolve, reject) { // Create a promise that uses it
        setTimeout(resolve, 1000);
    }).then (function () { // then() will have same PSD as Promise constructor
        assert (Dexie.Promise.PSD.promiseSpecificVariable == 3);
    });
});

Description

Analogous to Thread-specific data, Promise-specific data contains static data bound to the execution flow of a Promise.

Purpose

In the threading world, reentrant mutexes / recursive locking is an important pattern that enables one function to lock a mutex, then call other sub functions that also locks the same mutex without a deadlock arising. PSD makes that pattern possible in the Promise world.

Other usage samples includes anything that Thread-specific data is usable for.

In Dexie, PSD is used for:

  • Maintaining transaction scopes
  • Enabling reentrant write-locks on transactions
  • Enabling subscribers to db.on('ready') work on db before db.open() completes

Difference Between Thread-specific data and PSD

Thread-specific Data is one-dimentional. You can set Thread-static property that will be set for the currently running thread. PSD is a tree (or stack on most cases) where each new Promise instance will create its own frame that will derive from its parent. This makes PSD data automatically disappear when a Promise goes out of scope. This is also nescessary since Promise chains (unlike threads) can all root down the the same promise but be forked on certain frames.

Non-Standard

PSD is Dexie-proprietary invention and is not standardized in any Promise specificatotion.

How To Use

Dexie.Promise.newPSD(function() {
    // In this function, we have a Dexie.Promise.PSD to work with.
    Dexie.Promise.PSD.myVar = 3;
    
    new Dexie.Promise(function(resolve, reject){
        // Promise constructor will derive from current scope:
        alert (Dexie.Promise.PSD.myVar); // Will alert "3"
        // Let's resolve the promise to explain the then() method:
        setTimeout(resolve, 100);
    }).then (function(){
        // Here, we have the same PSD as when Promise instance was created
        alert (Dexie.Promise.PSD.myVar); // Will alert "3"
    }).catch (function() {
        alert (Dexie.Promise.PSD.myVar); // Would alert "3" as well
    });
});

alert (Dexie.Promise.PSD); // Will alert "null" (unless the code was called from another Promise)

Sub Scopes

In case calling Dexie.Promise.newPSD() when already in a PSD scope (Dexie.Promise.PSD !== null), the new PSD will derive prototypically from the outer PSD scope.

//
// top-level: Dexie.Promise.PSD === null
//
Dexie.Promise.newPSD(function() {
    //
    // Root-scope:
    //

    // Play with PSD:
    Dexie.Promise.PSD.myVar = 3; 
    alert (Dexie.Promise.PSD.myVar); // Will alert ("3") (obviously)

    Dexie.Promise.newPSD(function() {
        //
        // Sub-scope: Current PSD derives from parent PSD.
        //

        // Play with PSD: Override myVar but dont change parent value:
        Dexie.Promise.PSD.myOtherVar = 18;

        alert (Dexie.Promise.PSD.myVar); // Will alert ("3") (derived value)
        alert (Dexie.Promise.PSD.myOtherVar); // Will alert ("18") (direct value)   
    });

    // Back to root scope:

    alert (Dexie.Promise.PSD.myOtherVar); // Will alert ("null")
    alert (Dexie.Promise.PSD.myVar); // Will alert ("3")
});

// At this point, Dexie.Promise.PSD === null again.
Clone this wiki locally