🎨 Introduce Config::transactAsync

This commit is contained in:
Antonio Scandurra
2015-11-11 09:55:20 +01:00
parent ec52446b98
commit 38d713379f
3 changed files with 75 additions and 7 deletions

View File

@@ -589,6 +589,49 @@ describe "Config", ->
atom.config.transact ->
expect(changeSpy).not.toHaveBeenCalled()
describe ".transactAsync(callback)", ->
changeSpy = null
beforeEach ->
changeSpy = jasmine.createSpy('onDidChange callback')
atom.config.onDidChange("foo.bar.baz", changeSpy)
it "allows only one change event for the duration of the given promise if it gets resolved", ->
waitsForPromise ->
atom.config.transactAsync ->
atom.config.set("foo.bar.baz", 1)
atom.config.set("foo.bar.baz", 2)
atom.config.set("foo.bar.baz", 3)
Promise.resolve()
runs ->
expect(changeSpy.callCount).toBe(1)
expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined)
it "allows only one change event for the duration of the given promise if it gets rejected", ->
waitsForPromise shouldReject: true, ->
atom.config.transactAsync ->
atom.config.set("foo.bar.baz", 1)
atom.config.set("foo.bar.baz", 2)
atom.config.set("foo.bar.baz", 3)
Promise.reject()
runs ->
expect(changeSpy.callCount).toBe(1)
expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined)
it "allows only one change event even when the given callback throws", ->
waitsForPromise shouldReject: true, ->
atom.config.transactAsync ->
atom.config.set("foo.bar.baz", 1)
atom.config.set("foo.bar.baz", 2)
atom.config.set("foo.bar.baz", 3)
throw new Error("Oops!")
runs ->
expect(changeSpy.callCount).toBe(1)
expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined)
describe ".getSources()", ->
it "returns an array of all of the config's source names", ->
expect(atom.config.getSources()).toEqual([])

View File

@@ -677,6 +677,33 @@ class Config
finally
@endTransaction()
# Extended: Suppress calls to handler functions registered with
# {::onDidChange} and {::observe} for the duration of the {Promise} returned
# by `callback`. After the {Promise} is either resolved or rejected, handlers
# will be called once if the value for their key-path has changed.
#
# * `callback` {Function} that returns a {Promise}, which will be executed
# while suppressing calls to handlers.
#
# Returns a {Promise} that is either resolved or rejected according to the
# `{Promise}` returned by `callback`. If `callback` throws an error, a
# rejected {Promise} will be returned.
transactAsync: (callback) ->
@beginTransaction()
endTransaction = (resolveOrReject) => (args...) =>
@endTransaction()
resolveOrReject(args...)
try
result = callback()
new Promise (resolve, reject) =>
result
.then(endTransaction(resolve))
.catch(endTransaction(reject))
catch error
@endTransaction()
Promise.reject(error)
beginTransaction: ->
@transactDepth++

View File

@@ -418,13 +418,11 @@ class PackageManager
activatePackages: (packages) ->
promises = []
@config.beginTransaction()
for pack in packages
promise = @activatePackage(pack.name)
promises.push(promise) unless pack.activationShouldBeDeferred()
Promise.all(promises)
.then(=> @config.endTransaction())
.catch(=> @config.endTransaction())
@config.transactAsync =>
for pack in packages
promise = @activatePackage(pack.name)
promises.push(promise) unless pack.activationShouldBeDeferred()
Promise.all(promises)
@observeDisabledPackages()
@observePackagesWithKeymapsDisabled()
promises