Ogólnie promisy i eventy słabo współpracują, bo promise jest rozwiązywany raz, a event wielokrotnie (m.in. dlatego istnieją takie rzeczy jak RX i channele), ale w tym przypadku da się to w miarę elegancko zrobić, bez uciekania się do globali itp (choć mamy niestety coupling, ale bez wspomnianych wcześniej rozwiązań nie bardzo wiem czy da się tego uniknąć), przykład:
<button id="example">Example</button>
<button id="redraw">redraw</button>
const draw = (() => {
// Create a scoped variable inside a closure,
// so we can change it, without re-registering event:
let _value
// Register event inside a closure (just an example code):
document
.getElementById("example")
.addEventListener('click', event => {
console.log("Handling event...")
event.target.innerText = `${_value} | ${Math.random()}`
})
// Return an actual function that have acces to the lexical closure
return () => {
Promise.resolve(Math.random()) // Your promise goes here, instead of this fake
.then(value => {
// ... do some stuff
// Assign dynamic value to the ecnclosed equivalent:
_value = value
})
}
})() // Immidiatelly execute enclosing function to get the inner one
// First render:
draw()
// Register a redraw on click:
document.getElementById("redraw").addEventListener("click", draw)
CodePen: https://codepen.io/caderek/pen/vYYObNa?editors=1010
Alternatywnie z użyciem klasy (trochę dłuższe):
class MyClass {
constructor() {
this._value = null
document
.getElementById("example")
.addEventListener('click', event => {
console.log("Handling event...")
event.target.innerText = `${this._value} | ${Math.random()}`
})
this.draw = this.draw.bind(this)
}
draw() {
Promise.resolve(Math.random())
.then(value => {
// ...do some stuff
this._value = value
})
}
}
const myObject = new MyClass()
myObject.draw()
document.getElementById("redraw").addEventListener("click", myObject.draw)
CodePen: https://codepen.io/caderek/pen/VwwLqaP?editors=1010
W twoim przypadku to będzie coś w stylu:
const draw = (() => {
let _gd
document.getElementById("getChartImage").addEventListener("click", () => {
if (_gd) {
Plotly.toImage(_gd).then(url => {
img_jpg.attr("src", url)
Plotly.downloadImage(gd)
})
}
})
return () => {
Plotly.newPlot("plotly", data, layout, {
responsive: true,
displaylogo: false,
locale: "pl",
modeBarButtonsToRemove: ["toImage"]
}).then(gd => {
_gd = gd
})
}
})()
draw()
document.getElementById("redraw").addEventListener("click", draw)