如何从 JS 中的异步操作中获取值?

How to get a value from an async operations in JS?

我已经阅读了一些论坛并观看了一些关于异步操作和使用 promises 来解决此类问题的 youtube 视频,但他们只致力于更简单的功能等。它实际上并没有给我关于如何解决我的问题的提示。 我的脚本中有这个函数。

var coordinates = [];
    $(function(){
      function getcoordinates(){
          if(navigator.geolocation){
            var options = {
              enableHighAccuracy: true,
              timeout: 5000,
              maximumAge: 0
            };
             function success(pos) {
                var crd = pos.coords;
                userlat = crd.latitude;//this one
                userlong = crd.longitude;// and this one are the ones i want
              }
              function error(err) {
                console.warn(`ERROR(${err.code}): ${err.message}`);
              }
            navigator.geolocation.getCurrentPosition(success, error, options);//but I dont have an idea how to access those two from this API function.
          }
          else
            alert("Geolocation is not supported by this browser.");
        }

      $('#go').click(function(){
        console.log("outside success output: " + userlat);//this still shows 0
        console.log(coordinates);

        $.ajax({
          url:"dbphp.php",
          method:"POST",
          data:{userlong:coordinates[1], userlat:coordinates[2]},
          success:function(data){
          }
        })

      })
    })

如何 return userlat 和 userlong 的值并将其放入我的坐标数组中?

首先让我们就您所说的"async"的定义达成一致:一段非阻塞代码,将在满足条件后执行,对吗?

根据这个定义,您的代码中有一些 "async" 调用,navigator.geolocation.getCurrentPosition()$.ajax(),还有 .click()$()

其中每一个都会回调你提供的一个provided函数(callback)。

getCurrentPosition()的情况下,它接收3个参数,其中2个是分别在成功/失败时执行的回调(可选)和一个配置对象(可选)。你肯定处理得很好。

但是:

  1. 您的语法似乎有点错误,getcoordinates() 不是由单击按钮之前的任何内容触发的
  2. 无论哪种方式,您都不会在处理 .click() 处理程序中的 returned 值之前专门等待 getcoordinates() 完成
  3. 你不应该不必要地定义你的函数定义
  4. userlatuserlong 声明在哪里?
  5. 不要忘记数组是 0 索引的

TL;DR 玩这个:

function getCoordinates(thenCb, errorCb) {
    thenCb = thenCb || function () {};
    errorCb = errorCb || function () {};

    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(thenCb, errorCb, {
            enableHighAccuracy: true,
            timeout: 5000,
            maximumAge: 0
        });
    } else {
        alert('Geolocation is not supported by this browser.');
    }
}

$(function () {
    $('#go').click(function () {
        getCoordinates(function (pos) {
            $.ajax({
                url: 'dbphp.php',
                method: 'POST',
                data: { 
                    userlong: pos.coords.latitude, 
                    userlat: pos.coords.longitude 
                },
                success: function (data) {
                    // do stuff with data...
                }
            });
        }, function (err) {
            console.warn('Geolocation error ' + err.code + ': ' + err.message);
        });
    });
});

对于 ES6+ 版本:

const getCoordinates = (thenCb = () => {}, errorCb = () => {}) => {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(thenCb, errorCb, {
            enableHighAccuracy: true,
            timeout: 5000,
            maximumAge: 0
        });
    } else {
        alert('Geolocation is not supported by this browser.');
    }
};

$(() => {
    $('#go').click(() => {
        getCoordinates(({ coords }) => {
            const { userlong, userlat } = coords;
            $.ajax({
                url: 'dbphp.php',
                method: 'POST',
                data: { userlong, userlat },
                success: (data) => {
                    // do stuff with data...
                }
            });
        }, (err) => {
            console.warn(`Geolocation error ${err.code}: ${err.message}`);
        });
    });
});

注意 1:您可能希望根据您的需要和上下文重构它,避免在全局范围内设置 getCoordinates(),等等。

注意 2:在这种情况下等待 getCoordinates() 用户点击完成是可以的,因为尽管 "async",该函数会迅速 return 结果。通常当需要更长的时间来解决时,您可能希望 a) 触发点击处理程序之前的函数以记住其 return 值,b) 向用户显示加载状态。

关于 xhr 请求,请注意您正在使用 jQuery.ajax() 并且响应数据将在作为其第一个参数提供的 success 回调中提供。

此外,请务必查看文档:
- https://developer.mozilla.org/en-US/docs/Web/API/Geolocation
- https://api.jquery.com

如果有兴趣,请阅读如何使用 Promises,使回调代码更加消化:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

如果仍然感兴趣,请阅读如何使用 async / await 使 Promises 代码更摘要:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function