跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • js 异步 http 请求的返回值,如何赋值给一个变量?
未分類
9 10 月 2020

js 异步 http 请求的返回值,如何赋值给一个变量?

js 异步 http 请求的返回值,如何赋值给一个变量?

資深大佬 : css3 3

异步编程新新新新手, 不应该说编程新手

这几日在用 jsbox 构建一个自己的小工具,卡在了 http 异步请求这一块,请求返回值死活无法赋值给一个全局的变量给其他地方使用;

了解了异步的一些基础用法,有通过 then 获取的,有通过定义 async 函数获取的,还有回调函数获取的 但发现有个特点就是拿到的返回值,作用域均仍在内部,拿不出来这个返回值

// 调用 v 站的 api 例子,获取最新主题 function test() {    var result = undefined    let url = "https://www.v2ex.com/api/topics/latest.json"    return $http.get({      url: url    }).then(resp => {      var data = resp.data[0]['title']      return data    }) } 
//调用的获取返回值 async function getRet(){     var ret = await test();     console.log(ret);     return ret; }  getRet()  // 拿不到 ret 的值 

大佬有話說 (23)

  • 資深大佬 : Yumwey

    async/await 返回的是 promise,所以,知道怎么拿了吗?

  • 資深大佬 : kuanng

    getRet 这个函数返回的是一个 promise 吧

  • 資深大佬 : Jirajine

    异步就是这样的啊,你要非要用同步的风格写异步,那就把代码逻辑包在一个 async IIFE 里面,像这样
    (async function(){
    // your code here
    })()
    然后用 await 就能拿到包在 promise 里面的值了。

    还有个极其不推荐的办法是定义一个全局变量,然后异步代码里把结果赋值给这个变量,但你无法保证你取用这个变量的代码被调度到后面执行。

  • 主 資深大佬 : css3

    @css3 @Yumwey @kuanng
    这样可以,但我后面要用这个返回值的地方,是构建一个 webvirw, 它是不支持直接给一坨东西的,还是得赋值给变量才能用啊
    https://gist.github.com/seryte/e725987b2b18ccb43772a2b8ea182198

  • 資深大佬 : vision1900

    你在写 test 的时候就已经拿到了值,只是这个是异步的
    无论你怎么封装,都不可能用同步的方式拿到值
    async/await 是一层语法糖,只是写起来像同步的而已,实际还是依赖 promise 。也就是说实际还是异步代码

    getRet() 运行的上下文是同步的,一开始方向就搞错了,陷入了“封装陷阱”

  • 主 資深大佬 : css3

    @vision1900

  • 主 資深大佬 : css3

    @Jirajine 尝试过,不行的,取不到

  • 主 資深大佬 : css3

    @vision1900 所以,我怎么用同步的方法拿到异步的返回值?

  • 資深大佬 : Yumwey

    你非要同步的话,又不想再套 async/await 走逻辑的话,那就写个 emit

  • 資深大佬 : user8341

    @css3

    异步代码赋给全局变量。同步代码这边 setInterval,然后不断重试最后总能取到。

  • 資深大佬 : Jirajine

    @css3 你还是没看我在说什么。
    把所有代码都包进去,如果用全局变量赋值的话,很可能你后面取用的代码会先于你给全局变量赋值的异步代码执行,所以你会“取不到”,因为你取的时候还没赋值呢。这就是异步。

  • 資深大佬 : vision1900

    @css3 没有办法,同步代码不可能立即获得异步的返回,只能等待环境(浏览器或者 Node )告诉你异步代码执行结束了,你才能真正“拥有”返回值. 处理返回,要不用回调函数,要不用 Promise

    var result = undefined
    let url = “https://www.v2ex.com/api/topics/latest.json”
    return $http.get({
    url: url
    }).then(resp => {
    var data = resp.data[0][‘title’]
    // 这里你获得了返回,直接用就完了
    })

    如果你需要封装成函数让代码看起来更模块化,可以传一个回调函数
    funtion test(callback) {
    var result = undefined
    let url = “https://www.v2ex.com/api/topics/latest.json”
    return $http.get({
    url: url
    }).then(resp => {
    var data = resp.data[0][‘title’]
    callback(data);
    })
    }

    function useData(data) {
    // 任何依赖于异步返回的代码都放这里
    console.log(data)
    }

    test(useData);

    // 高级一点的做法是返回一个 Promise
    funtion test() {
    var result = undefined
    let url = “https://www.v2ex.com/api/topics/latest.json”
    return $http.get({
    url: url
    }).then(resp => {
    var data = resp.data[0][‘title’]
    return data; // .then 返回类型是 Promise,这个 Promise 会 resolve 为 .then 里的函数返回值
    })
    }

    test().then(data => {
    // 任何依赖于异步返回的代码都放这里
    console.log(data)
    })

    // 再高级一点是用 async/await,不过心里要明白,async/await 只是语法糖,实际还是 promise 。之所以高级是因为视觉上像同步代码,增强了可读性
    funtion test() {
    var result = undefined
    let url = “https://www.v2ex.com/api/topics/latest.json”
    return $http.get({
    url: url
    }).then(resp => {
    var data = resp.data[0][‘title’]
    return data
    })
    }

    async main() {
    const data = await test();
    // 任何依赖于异步返回的代码都放这里
    console.log(data)
    }

    main();

  • 資深大佬 : hazyzh

    我怎么用同步的方法拿到异步的返回值?

    ???
    这个问题问的非常好!这需要利用量子力学的一个概念 **协变量子场**, [空间和时间都不是连续的,宇宙时间,世界的一切,包括时空,都只是协变量子场的表现形式] 。

    建议你研究一下这个,这个问题一解决 可以从根本上一举攻克 js 回掉地狱的历史性难题。

  • 資深大佬 : autoxbc

    异步是语言级的特性,没有「不支持这样的格式」的说法

  • 資深大佬 : GzhiYi

    关键字是:宏任务和微任务

  • 資深大佬 : aaronlam

    你应该要把需要用到这个 await 返回的值的操作直接就写在 await 之后,这是最简单的办法了。因为 async await 说白了其根本就是 promise,你可以理解为 await 之后的代码还原成 promise 之后,就是在 then 里面的代码。

    “` javascript
    new promise((resolve, reject)=>{…}).then((value)=>{ // await 之后的代码就是类似在这里的代码!!] })。
    “`

    要是你非要把 then 里的 value 拿出来(但是按照我的理解,貌似这样有点脱裤子放屁的感觉),那按照你目前提供的代码,可以在外部写一个类似下面 getAsyncReturnValue 的函数

    “` javascript
    function getAsyncReturnValue(value)
    {
    // 这里做你要拿到 value 后要做的事
    }

    function test() {
    var result = undefined
    let url = “https://www.v2ex.com/api/topics/latest.json”
    $http.get({
    url: url
    }).then(resp => {
    var data = resp.data[0][‘title’]
    return data
    })
    }

    (async ()=> {
    const value = await test();
    getAsyncReturnValue(value)
    }())
    //调用的
    “`

  • 資深大佬 : kwrush

    想要同步获取异步结果,那可以自己实现一个简单的 event emitter 或者观察者模式,比如
    class MyEmitter () {
    constructor() {
    this._events = [];
    }

    on = (event, listener) => {
    if (this._events[event] == null) {
    this._events[event] = [];
    }
    this._events[event].push(listener);
    }

    removeListener = (event, listener) => {…}
    emit = (event, data) => {
    if (this._events[event] == null) {
    throw new Error(‘no event found’);
    }

    const fun = (listener) => listener(data);
    this._events[event].forEach(fun);
    }
    }

    const emitter = new MyEmitter();

    // 你要使用数据的地方
    emitter.on(‘getRes’, (res) => console.log(res));
    …

    const getRes = async () => {
    const res = await yourAsyncFun();
    emitter.emit(‘getRes’, res);
    }

    await getRes();

  • 資深大佬 : shenyu1996

    await 变同步 或者放在异步的回调里

  • 資深大佬 : Arrowing

    把.then 及其后面的代码删掉

  • 資深大佬 : Doracis

    请求回来的 result,用方法调用,作为形参,这样试试?
    …then((res) => {
    this.anotherFunc(res)
    })

  • 主 資深大佬 : css3

    @vision1900 在我这个场景,还是不太行
    https://gist.github.com/seryte/451054ee7a49fe9bb74427898b22f4a9

  • 主 資深大佬 : css3

    @vision1900
    @aaronlam
    @kwrush
    @Doracis
    @Arrowing
    @shenyu1996
    大佬帮忙看一下,我 append 了原始需求

  • 資深大佬 : Arrowing

    “`javascript
    function test() {
    var result = undefined
    let url = “https://www.v2ex.com/api/topics/latest.json”
    let res = $.get({ // 假设支持 jQuery,V2ex 控制台下可测试
    url: url,
    async: false // 使用同步请求
    })
    return res.responseJSON[0][‘title’]
    }
    “`

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具