JS Promise 等待嵌套异步函数
JS Promise wait for nested asynchronous function
我在正确计时 2 个异步操作时遇到问题,因此外部函数会等待内部函数完成后再继续。我尝试实施的解决方案基于使用 ES2015 的现有解决方案,因此我无法使用 await,必须使用 Promises。
解决方案分为多个 classes,为了便于概述,我将其称为 Main、Invoker 和 Inner。因此 Main class 使用 Invoker 的实例异步执行来自 Inner class 的命令,然后应该等待响应,这有效但它不等待异步 Image.onload() 来自内部 class.
的 setSize()
class Inner extends Component{
setSize(size){
const newImage = { url: null, imageName: canvasImage.imageName};
... some stuff...
const tempImage = new Image();
tempImage.src = canvas.toDataURL();
tempImage.onload = function(){
... some stuff...
const tempCanvas = document.createElement("canvas");
const tempCtx = tempCanvas.getContext("2d");
tempCtx.drawImage(image, x, y, xa, ya);
newImage.url = tempCanvas.toDataURL();
}
return Promise.resolve(newImage);
}
}
class Main{
resize(size){
imageData = this.execute(commandName,'setSize', size);
imageData.then(image => {
... do stuff with image data...
});
}
execute(commandName, ...args) {
return this._invoker.execute(commandName, ...args);
}
}
class Invoker{
execute(...args) {
let [command] = args;
if (isString(command)) {
command = commandFactory.create(...args);
}
return this._invokeExecution(command).then((value) => {
this.clearRedoStack();
return value;
});
}
}
我已经尝试在 onload 函数内的 setSize 函数中移动“return Promise.resolve(newImage),但是由于缺少解决。
有什么想法吗?
您需要 return 承诺并在 onload 中解决它。
setSize () {
return new Promise((resolve, reject) => {
...
tempImage.onload = function () {
...
resolve(newimage)
}
})
}
因为 setSize
函数在 onload
中使用基于回调的语法,您需要等到 onload 函数被浏览器调用,
您可以 return 来自 setSize
的承诺,并处理 onload
对 resolve
和 onerror
对 reject
的处理,例如:
setSize(size){
return new Promise((res, rej) => {
const newImage = { url: null, imageName: canvasImage.imageName};
... some stuff...
const tempImage = new Image();
tempImage.src = canvas.toDataURL();
tempImage.onload = function(){
... some stuff...
const tempCanvas = document.createElement("canvas");
const tempCtx = tempCanvas.getContext("2d");
tempCtx.drawImage(image, x, y, xa, ya);
newImage.url = tempCanvas.toDataURL();
res(newImage);
}
tempImage.onerror = function(error) {
rej(error)
}
})
}
我在正确计时 2 个异步操作时遇到问题,因此外部函数会等待内部函数完成后再继续。我尝试实施的解决方案基于使用 ES2015 的现有解决方案,因此我无法使用 await,必须使用 Promises。
解决方案分为多个 classes,为了便于概述,我将其称为 Main、Invoker 和 Inner。因此 Main class 使用 Invoker 的实例异步执行来自 Inner class 的命令,然后应该等待响应,这有效但它不等待异步 Image.onload() 来自内部 class.
的 setSize()class Inner extends Component{
setSize(size){
const newImage = { url: null, imageName: canvasImage.imageName};
... some stuff...
const tempImage = new Image();
tempImage.src = canvas.toDataURL();
tempImage.onload = function(){
... some stuff...
const tempCanvas = document.createElement("canvas");
const tempCtx = tempCanvas.getContext("2d");
tempCtx.drawImage(image, x, y, xa, ya);
newImage.url = tempCanvas.toDataURL();
}
return Promise.resolve(newImage);
}
}
class Main{
resize(size){
imageData = this.execute(commandName,'setSize', size);
imageData.then(image => {
... do stuff with image data...
});
}
execute(commandName, ...args) {
return this._invoker.execute(commandName, ...args);
}
}
class Invoker{
execute(...args) {
let [command] = args;
if (isString(command)) {
command = commandFactory.create(...args);
}
return this._invokeExecution(command).then((value) => {
this.clearRedoStack();
return value;
});
}
}
我已经尝试在 onload 函数内的 setSize 函数中移动“return Promise.resolve(newImage),但是由于缺少解决。 有什么想法吗?
您需要 return 承诺并在 onload 中解决它。
setSize () {
return new Promise((resolve, reject) => {
...
tempImage.onload = function () {
...
resolve(newimage)
}
})
}
因为 setSize
函数在 onload
中使用基于回调的语法,您需要等到 onload 函数被浏览器调用,
您可以 return 来自 setSize
的承诺,并处理 onload
对 resolve
和 onerror
对 reject
的处理,例如:
setSize(size){
return new Promise((res, rej) => {
const newImage = { url: null, imageName: canvasImage.imageName};
... some stuff...
const tempImage = new Image();
tempImage.src = canvas.toDataURL();
tempImage.onload = function(){
... some stuff...
const tempCanvas = document.createElement("canvas");
const tempCtx = tempCanvas.getContext("2d");
tempCtx.drawImage(image, x, y, xa, ya);
newImage.url = tempCanvas.toDataURL();
res(newImage);
}
tempImage.onerror = function(error) {
rej(error)
}
})
}