异步/等待不按我期望的那样

时间:2018-12-06 17:42:36

标签: javascript jquery rest promise async-await

请忍受我已经进入一个新项目并试图将其全部纳入其中。在过去的两天里我一直在取得进展,但似乎无法克服最后的困难。希望我能正确解释。

我正在加载一个Web表单,并且需要对API进行调用,以基于当前加载的数据获取一些可能存在或可能不存在的信息。我已经简化了页面,基本上就是这样。

...Get some information the user wants and start to do some work to load 
up the page and set up the form.
...old stuff working fine...

//Time for my new stuff
var testValue
async function test() {
    await http.post(appConfig.serviceRootUrl + '/api/XXX/YYY', 
    { mProperty: myObject.collectionInObject.itemInCollection }).then(function (result) {
        if (result.length < 1) {
            testValue= false;
        }
        else if (result[0].infoIWant.trim().length > 0) {
            testValue= true;
        }
    });
}
test(); 

//Originally above in the if I was just seeing if I got a result 
//and setting testValue to true/false but changed it for debugging 
//and I am surely getting back correct values when the data exists 
//or result.length zero when no data for it


...Do a bunch of more stuff that is old and working correctly....

//Test the new stuff up above

 alert(testValue);

在大多数情况下,我会在警报中返回正确的对或错,但有时我会返回不确定的状态。我猜未定义是因为它正在异步/等待完成之前进入警报。我的印象是它不会超出我称之为“ test();”的那一行。我以为它实际上使它停止了test()以下的任何内容;直到等待结束。最初它有点复杂,但我一直在简化它,以使其(希望)更加基础/简单。

我在思想或实现方面缺少什么?

在此刻我追逐自己的尾巴时,任何帮助都非常感激。

3 个答案:

答案 0 :(得分:4)

这不是异步功能的工作方式。该功能似乎只在功能本身内部等待。在函数外部,它被调用并同步返回promise。

换句话说,如果您写:

 let t = test()

t是一个承诺,它将在test()返回时解决。在您当前的代码中,如果要在功能之外进行响应,则需要类似以下内容:

async function test() {
    let result = await http.post(appConfig.serviceRootUrl + '/api/XXX/YYY', 
    { mProperty: myObject.collectionInObject.itemInCollection })
    if (result.length < 1) return false
    else if (result[0].infoIWant.trim().length > 0)  return true;
}


// test is an async function. It returns a promise.
test().then(result => alert("result: " + result ))

根据评论进行编辑
这是使用Axios进行http.post命令的工作版本:

async function test() {
    let result = await axios.post('https://jsonplaceholder.typicode.com/posts', 
    { mProperty: "some val" })
    return result.data
}


// test is an async function. It returns a promise.
test().then(result => console.log(result ))
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>

答案 1 :(得分:2)

这样做如何?

...Get some information the user wants and start to do some work to load 
    up the page and set up the form.
    ...old stuff working fine...

    //Time for my new stuff
    var testValue
    async function test() {
       let promise = new Promise( (resolve, reject) => resolve( http.post(appConfig.serviceRootUrl + '/api/XXX/YYY', 
        { mProperty: myObject.collectionInObject.itemInCollection }).then(function (result) {
            if (result.length < 1) {
                testValue= false;
            }
            else if (result[0].infoIWant.trim().length > 0) {
                testValue= true;
            }
        })));
     await promise;
 alert(testValue);
    }
    test(); 

    //Originally above in the if I was just seeing if I got a result 
    //and setting testValue to true/false but changed it for debugging 
    //and I am surely getting back correct values when the data exists 
    //or result.length zero when no data for it


    ...Do a bunch of more stuff that is old and working correctly....

    //Test the new stuff up above

答案 2 :(得分:-6)

如果您使用.then()语法,请不要使用await,反之亦然。我对浏览器与async / await的兼容性不正确,似乎我并没有跟上浏览器脚本的发展,而赞成Node。而且,由于您使用的是jQuery,$.ajax()对于您可能是一个不错的选择,因为您不需要async / await或.then(),您可以这样做:

$.ajax(appConfig.serviceRootUrl + '/api/XXX/YYY', {
    method: 'POST',
    data: { mProperty: myObject.collectionInObject.itemInCollection }
}).done(function(data) {
    //use result here just as you would normally within the `.then()`
})

我希望这比我的原始答案更有帮助。