Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8116235
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 6, 20262026-06-06T03:45:23+00:00 2026-06-06T03:45:23+00:00

While making my way through the wonderful world of IndexedDB, I came across code

  • 0

While making my way through the wonderful world of IndexedDB, I came across code like this from Mozilla’s test suite:

/**
 * Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

var testGenerator = testSteps();

function testSteps()
{
  const IDBObjectStore = Components.interfaces.nsIIDBObjectStore;
  const name = this.window ? window.location.pathname : "Splendid Test";
  const description = "My Test Database";

  var data = [
    { name: "inline key; key generator",
      autoIncrement: true,
      storedObject: {name: "Lincoln"},
      keyName: "id",
      keyValue: undefined,
    },
    { name: "inline key; no key generator",
      autoIncrement: false,
      storedObject: {id: 1, name: "Lincoln"},
      keyName: "id",
      keyValue: undefined,
    },
    { name: "out of line key; key generator",
      autoIncrement: true,
      storedObject: {name: "Lincoln"},
      keyName: undefined,
      keyValue: undefined,
    },
    { name: "out of line key; no key generator",
      autoIncrement: false,
      storedObject: {name: "Lincoln"},
      keyName: null,
      keyValue: 1,
    }
  ];

  for (let i = 0; i < data.length; i++) {
    let test = data[i];

    let request = mozIndexedDB.open(name, i+1, description);
    request.onerror = errorHandler;
    request.onupgradeneeded = grabEventAndContinueHandler;
    let event = yield;

    let db = event.target.result;

    let objectStore = db.createObjectStore(test.name,
                                           { keyPath: test.keyName,
                                             autoIncrement: test.autoIncrement });

    request = objectStore.add(test.storedObject, test.keyValue);
    request.onerror = errorHandler;
    request.onsuccess = grabEventAndContinueHandler;
    event = yield;

    let id = event.target.result;
    request = objectStore.get(id);
    request.onerror = errorHandler;
    request.onsuccess = grabEventAndContinueHandler;
    event = yield;

    // Sanity check!
    is(test.storedObject.name, event.target.result.name,
                  "The correct object was stored.");

    request = objectStore.delete(id);
    request.onerror = errorHandler;
    request.onsuccess = grabEventAndContinueHandler;
    event = yield;

    // Make sure it was removed.
    request = objectStore.get(id);
    request.onerror = errorHandler;
    request.onsuccess = grabEventAndContinueHandler;
    event = yield;

    ok(event.target.result === undefined, "Object was deleted");
    db.close();
  }

  finishTest();
  yield;
}

Their other tests are written in a similar style, as opposed to the typical “pyramid of doom” style you see with IndexedDB due to asynchronous callbacks being stacked together (and, of course, generators aren’t widely supported beyond Firefox..).

So, this code from Mozilla is somewhat appealing and intriguing to me as it looks very clean, but I’m not totally sure what yield is doing in this context. Can anyone help me understand this?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-06T03:45:24+00:00Added an answer on June 6, 2026 at 3:45 am

    This is a brilliant piece of code which leverages the powerful new features of JavaScript 1.7 exposed by Firefox, and since IndexedDB is only supported by Firefox and Chrome (in 2012) I’d say that it’s an excellent trade off (Note that as of at least 2022, indexedDB is supported in all major browsers).

    The first line of the code creates a generator from the function testSteps and assigns it to the variable testGenerator. The reason we are using generators is because IndexedDB is a purely asynchronous API; and asynchronous programming and nested callbacks are a pain. Using generators eases this pain by allowing you to write asynchronous code that looks synchronous.

    Note: If you want to know how to leverage the power of generators to make asynchronous code synchronous read the following article.

    To explain how generators are useful to make asynchronous programming bearable consider the following code:

    var name = "Test";
    var version = 1.0;
    var description = "Test database.";
    
    var request = mozIndexedDB.open(name, version, description);
    
    request.onupgradeneeded = function (event) {
        var db = event.target.result;
    
        var objectStore = db.createObjectStore("Thing", {
            keyPath: "id",
            autoIncrement: true
        });
    
        var object = {
            attributeA: 1,
            attributeB: 2,
            attributeC: 3            
        };
    
        var request = objectStore.add(object, "uniqueID");
    
        request.onsuccess = function (event) {
            var id = event.target.result;
            if (id === "uniqueID") alert("Object stored.");
            db.close();
        };
    };
    

    In the above code we requested for a database named Test. We requested for the database version 1.0. Since it didn’t exist the onupgradeneeded event handler was fired. Once we got the database we created an object store on it, added an object to the object store, and after it was saved we closed the database.

    The problem with the above code is that we are requesting for the database and doing other operations related to it asynchronously. This could make the code very difficult to maintain as more and more nested callbacks are employed.

    To solve this problem we use generators as follows:

    var gen = (function (name, version, description) {
        var request = mozIndexedDB.open(name, version, description);
    
        request.onupgradeneeded = grabEventAndContinueHandler;
    
        var event = yield;
    
        var db = event.target.result;
    
        var objectStore = db.createObjectStore("Thing", {
            keyPath: "id",
            autoIncrement: true
        });
    
        var object = {
            attributeA: 1,
            attributeB: 2,
            attributeC: 3
        };
    
        request = objectStore.add(object, "uniqueID");
    
        request.onsuccess = grabEventAndContinueHandler;
    
        event = yield;
    
        var id = event.target.result;
    
        if (id === "uniqueID") alert("Object stored.");
    
        db.close();
    }("Test", 1.0, "Test database."));
    

    The grabEventAndContinueHandler function is defined after the generator as follows:

    function grabEventAndContinueHandler(event) {
        gen.send(event);
    }
    

    The generator is started as follows:

    gen.next();
    

    Once the generator is started a request is made to open a connection to the given database. Then grabEventAndContinueHandler is attached as an event handler to the onupgradeneeded event. Finally we yield or pause the generator using the keyword yield.

    The generator is automatically resumed when the gen.send method is called from the grabEventAndContinueHandler function. This function simply takes a single argument called event and sends it to the generator. When the generator is resumed the sent value is stored in a variable called event.

    To recap, the magic happens here:

    // resume the generator when the event handler is called
    // and send the onsuccess event to the generator
    request.onsuccess = grabEventAndContinueHandler;
    
    // pause the generator using the yield keyword
    // and save the onsuccess event sent by the handler
    var event = yield;
    

    The above code makes it possible to write asynchronous code as if it were synchronous. To know more about generators read the following MDN article. Hope this helps.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I stumbled on a way to crash excel in Workbook_Open while making an .xla
I just ran into this issue while making a GET request to a node.js
I'm starting with Ruby, and while making some test samples, I've stumbled against an
This question is regarding the behavior I observed while using const_cast for making a
I'm part-way through making a simple comments system with PHP. With every comment that
I was wondering if there was a way to completely lock my code while
While making some final tests of a class-library that I'm writing for Windows Mobile
While making a little Pong game in C++ OpenGL, I decided it'd be fun
While making AutoHotkey-script I encountered the following problem. I need navigate listbox (one position
Iam getting OutOfMemoryException while making remote method call. RemoteEntity.SetLocalStore(DATASET); passed value is dataset. Note

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.