我遇到了一种情况,需要我弹出一个窗口供用户做出选择,在窗口关闭后,根据用户输入并发出另一个http请求。我不知道如何在弹出窗口后等待。
async function checkRemote(url1, url2) {
var resp
resp = await fetch(url1).then(r => r.json())
if (r.condition1 == 100) {
setState({showPopup: true}) //in a reactjs app
//how do I do await here to wait for the popup being closed
//get the user choice in variable "proceed"
}
if (proceed) {
resp = await fetch(url2)
//do some more work
}
}
创建一个承诺,在弹出关闭事件处理程序中解决它,并在函数中等待它。
var popupClosed = new Promise(function(resolve, reject) {
// create popup close handler, and call resolve in it
});
async function checkRemote(url1, url2) {
var resp
resp = await fetch(url1).then(r => r.json())
if (r.condition1 == 100) {
setState({showPopup: true}) //in a reactjs app
var closed = await popupClosed;
}
if (proceed) {
resp = await fetch(url2)
//do some more work
}
}
根据@hikmat-gurbanli的回答,这是一个可行的解决方案。这个想法是保存解析函数,以便将来某个句柄可以调用它来解锁异步函数。
const fetch = require('node-fetch')
var savedResolve;
test("http://localhost/prod/te.php");
async function test(url) {
await checkRemote(url)
console.log("completed")
}
var popupClosed = new Promise(function(resolve, reject) {
// create popup close handler, and call resolve in it
console.log("got here")
savedResolve = resolve;
});
async function checkRemote(url1) {
var resp
resp = await fetch(url1).then(r => r.text())
console.log("resp " + resp)
//setState({showPopup: true}) //in a reactjs app
var result = await popupClosed;
console.log("result: ")
console.log(result)
}
处理程序只需调用
savedResolve.resolve("Yes")
,它将在第 checkRemote
行解锁异步函数
var result = await popupClosed;
let passNextStep = false
$('#user-input').click(() => passNextStep = true)
async function myFunc() {
// do stuff before
await waitUserInput() // wait until user clicks
// do stuff after
// waitUserInput() can be reused as needed
}
myFunc()
// -------------- Helpers --------------
async function waitUserInput() {
while (passNextStep === false) await timeout(50)
next = false
}
async function timeout(ms) {
return new Promise(res => setTimeout(res, ms))
}
请参阅此工作片段
// this is an async timeout util
const timeout = async ms => new Promise(res => setTimeout(res, ms));
let next = false; // this is to be changed on user input
let n = 1;
async function waitUserInput() {
while (next === false) await timeout(50); // pause script but avoid browser to freeze ;)
next = false; // reset var
}
async function myFunc() {
$('#text').append(`* waiting user input...<br>`)
await waitUserInput();
$('#text').append(`* user has clicked ${n++} time(s)<br>`)
myFunc()
}
$('#user-input').click(() => next = true)
myFunc()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id='user-input' style='padding:15px;color:white; background: tomato; border: 0; border-radius:8px; font-weight: bold'>CLICK ME !</button>
<div id='text'>
</div>
变量
next
可用于存储用户输入值,如下所示:
const userResponse = await waitUserInput(); // get user input value
// this is an async timeout util
const timeout = async ms => new Promise(res => setTimeout(res, ms));
let next = false; // this is to be changed on user input
async function waitUserInput() {
while (next === false) await timeout(50); // pause script but avoid browser to freeze ;)
const userInputVal = next;
next = false; // reset var
return userInputVal;
}
async function myFunc() {
$('#text').append(`* waiting user input...<br>`)
const userResponse = await waitUserInput();
$('#text').append(`* user choice is ${userResponse}<br>`)
myFunc()
}
$('#user-input').click(function() { next = $('#text-input').val() })
myFunc()
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id='text-input' type='text'/>
<button id='user-input' style='padding:15px;color:white; background: tomato; border: 0; border-radius:8px; font-weight: bold'>SUBMIT !</button>
<div id='text'>
</div>
这是一个非常简约的示例,其中异步函数等待用户输入而不进行轮询,在此示例中单击按钮即可解决承诺:
async function testFunction(){
debug.log("some code");
await waitForContinue(); //wont continue past this point, unless the continue button is pressed
debug.log("some other code");
}
function waitForContinue() {
return new Promise(resolve => {
document.getElementById("Continue").addEventListener('click', function (e) {
resolve();
}, { once: true }); //Event listener is removed after one call
});
}
我在这个线程中花了很多时间——其中大部分时间试图正确使用 .catch。谢谢大家。这是一个等待控件(按钮)并使用 .then 和 .catch 的最小程序。
<!DOCTYPE html>
<html>
<head>
<title> await on button </title>
<meta charset="UTF-8">
<script src="/cssjsphp/incjs1.js"></script>
<script>
"use strict";
let fnresolve, fnreject, nres=0, nrej=0; // globals
window.onload = async function() {
zlog (1,'push either button');
while (true) {
let p = new Promise((res, rej) => { fnresolve = res; fnreject=rej; } );
await p
.then( (what) => { nres+=1; zlog(2,what); } )
.catch((what) => { nrej+=1; zlog(2,what); } );
}
}
function zlog(typ,msg) {
if (typ==2) document.getElementById('zlog').innerHTML += nres+' resolves, '+nrej+' rejects, this one was '+msg+'<br />';
document.getElementById('zlog').innerHTML += 'push either button<br />';
}
</script>
</head>
<body>
<button onclick='fnresolve("OK");'> RESOLVE </button>
<button onclick='fnreject("NG");''> REJECT </button><br /><br />
<div id='zlog'></div>
</body>
</html>