javascript 如何防止在所有函数中添加await/async?

9wbgstp7  于 2023-05-12  发布在  Java
关注(0)|答案(1)|浏览(170)

bounty还有3天到期。回答此问题可获得+50声望奖励。Handsome Nerd希望引起更多关注这个问题。

从一个非常简单的例子开始,要求用户确认一个选择:

let a = function(){ return window.confirm( "Proceed" ); };
let b = function(){ console.log("b: " + a() ); };
let c = function(){ b(); console.log( "after b" ); };
c();
c();

window.confirm()是一个异步事件,但函数以同步方式运行,并阻止执行,直到它被解决。
将其更改为使用自定义UI,该UI使用await阻止执行,直到用户响应。但是await documentation声明:
await运算符用于等待Promise。它只能在async函数内部使用。
因此,包含await表达式的函数必须被设置为async并返回一个promise,而不是之前的值,现在a()不会阻塞执行:

let a = async function(){
  let conf = document.createElement( "DIV" );
  conf.className = 'confirm';
  let message = document.createElement( "DIV" );
  message.className = 'confirm-message';
  message.innerText = 'Proceed';
  conf.appendChild( message );
  let ok = document.createElement( "BUTTON" );
  ok.innerText = 'Ok';
  conf.appendChild( ok );
  let cancel = document.createElement( "BUTTON" );
  cancel.innerText = 'Cancel';
  conf.appendChild( cancel );
  document.body.appendChild( conf );
  let v = await new Promise(
    response => {
      ok    .addEventListener( "click", ()=>{ response(true ); }, false );
      cancel.addEventListener( "click", ()=>{ response(false); }, false );
    }
  );
  conf.remove();
  return v;
};
let b = function(){ console.log("b: " + a() ); };
let c = function(){ b(); console.log( "after b" ); };
c();
c();
.confirm { display: grid; width: min-content; grid-template-columns: 10em 10em; grid-gap: 0.5em; grid-auto-rows: 1.4em; text-align: center; border: 1px #777 solid; background-color: #AAA; padding: 0.5em; }
.confirm > .confirm-message { grid-column: 1 / 3; }

这只是将问题向上移动到调用堆栈,后续函数需要使用await/async来确保它们等待用户输入解决:

let a = async function(){
  let conf = document.createElement( "DIV" );
  conf.className = 'confirm';
  let message = document.createElement( "DIV" );
  message.className = 'confirm-message';
  message.innerText = 'Proceed';
  conf.appendChild( message );
  let ok = document.createElement( "BUTTON" );
  ok.innerText = 'Ok';
  conf.appendChild( ok );
  let cancel = document.createElement( "BUTTON" );
  cancel.innerText = 'Cancel';
  conf.appendChild( cancel );
  document.body.appendChild( conf );
  let v = await new Promise(
    response => {
      ok    .addEventListener( "click", ()=>{ response(true ); }, false );
      cancel.addEventListener( "click", ()=>{ response(false); }, false );
    }
  );
  conf.remove();
  return v;
};
let b = async function(){ let v = await a(); console.log("b: " + v ); };
let c = async function(){ let v = await b(); console.log( "after b" ); };
(async function(){
  let c1 = await c();
  let c2 = await c();
})();
.confirm { display: grid; width: min-content; grid-template-columns: 10em 10em; grid-gap: 0.5em; grid-auto-rows: 1.4em; text-align: center; border: 1px #777 solid; background-color: #AAA; padding: 0.5em; }
.confirm > .confirm-message { grid-column: 1 / 3; }

有没有一种方法可以使用新的await语法来阻止执行,而不改变所有调用函数的签名,并使它们成为async(以模仿使用内置window.confirm() function的示例)?

yr9zkbsy

yr9zkbsy1#

您应该使用then()函数。然后在实现promise后返回async函数的结果。

// First define your main async function. 
let a = async function(){
  let v = await new Promise(
    response => {
      ok    .addEventListener( "click", ()=>{ response(true ); }, false );
      cancel.addEventListener( "click", ()=>{ response(false); }, false );
    }
  );
 
  return v;
};

// Then get the results of your async function

let b = a.then((result) => { 
   console.log("b: " + result ); 
});

相关问题