回调转promise,如何判断哪个分支返回promise

kingyo 2020-11-01 11:05:28
刚学javascript不久,有一个基于回调风格的调用,想把他转为基于Promise风格的

funA(res =>{
if (res)
funIf({()=> {
console.log('in if callback');
})
else
funElse(() => {
console.log('in else callback');
})
});

我是这么转的(假设有同名的promise风格的方法):

funA().then(res => {
if (res)
return funIf(); //if分支的Promise
else
return funElse(); //else分支的Promise
}).then(() => {
//这里我怎么知道是哪个分支过来的?
console.log('in if or else?');
});

我想问的是,我在后面的then里,如何能知道,这个到底前面then里面的哪个分支?
或者说,我不应该采用这种模式?
...全文
4667 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
泡泡鱼_ 2020-11-04
  • 打赏
  • 举报
回复
刚去找了下微信相关的接口,简化一下: wxp.js:找接口找到的=>https://blog.csdn.net/zzwwjjdj1/article/details/85316961

/**
 * wxp.js
 */
class wxp {
  static api(wxApiname: string, options?: any) {
    return new Promise((resolve, reject) => {
      wx[wxApiname]({...options, success: resolve, fail: reject})
    })
  }
}
页面应用:

let wxp = require('./wxp.js');
wxp.api('getSetting').then((res: any) => {
  if(res.authSetting['scope.userInfo']){
    wxp.api('getUserInfo').then((res: any) => {
      console.log('获取用户信息成功');
      // 可以将 res 发送给后台解码出 unionId
      this.globalData.userInfo = res.userInfo;
      wx.setStorageSync('userinfo', res.userInfo);
      this.getSession3rd();
    })
  }else{
    console.log('没有授权,需要在界面上授权');
    wxp.api('switchTab', {url: '/pages/my/my'})//.then()
  }
})
这样就好了。没必要非得像下面那样再绕一次:

let wxp = require('./wxp.js');
wxp.api('getSetting').then((res: any) => {
  return res.authSetting['scope.userInfo'] ? 'getUserInfo' : 'switchTab'
}).then(apiName => {
  if(apiName === 'getUserInfo') {
    wxp.api(apiName).then((res: any) => {
      console.log('获取用户信息成功');
      // 可以将 res 发送给后台解码出 unionId
      this.globalData.userInfo = res.userInfo;
      wx.setStorageSync('userinfo', res.userInfo);
      this.getSession3rd();
    })
  } else {
    //处理switchTab相关事务
    console.log('没有授权,需要在界面上授权');
    wxp.api(apiName, {url: '/pages/my/my'})//.then()
  }
})
又或者

let wxp = require('./wxp.js');
wxp.api('getSetting').then((res: any) => {
  return res.authSetting['scope.userInfo']
    ? wxp.api('getUserInfo')
    : wxp.api('switchTab', {url: '/pages/my/my'});

}).then((res: any) => {
  /**
   * 这里我用的res.errMsg.indexOf('getUserInfo') != -1来做为判断依据。
   * 是我随便找了一个,看到成功后也有这么一个errMsg
   * 反正大概意思就是你找到对应接口的一个辨别方式即可。可能是某个特定的属性,也可能是共同的属性,但值可以用来区分
   */
  if(res.errMsg.indexOf('getUserInfo') != -1) {
    console.log('获取用户信息成功');
    // 可以将 res 发送给后台解码出 unionId
    this.globalData.userInfo = res.userInfo;
    wx.setStorageSync('userinfo', res.userInfo);
    this.getSession3rd();
  } else {
    console.log('没有授权,需要在界面上授权');
  }
})

这种的话,你对getSetting的异常捕捉.catch得写在.then之前了。否则后面返回的是getUserInfo或switchTab
泡泡鱼_ 2020-11-03
  • 打赏
  • 举报
回复
其实,你这个一层封装就可以了吧。类似于下面这样子:

const wxp = window.wxp || {};
wxp.getSetting = function() {
  return new Promise(function(resolve, reject) {
    wx.getSetting({
      success: (res: any) => {
        resolve(res.authSetting['scope.userInfo'])
      },
      error: (err: any) => {
        reject(err)
      }
    })
  })
}
wxp.getSetting()
  .then((auth: any) => {
    //原有的业务逻辑
    if(auth) {
      wx.getUserInfo({
        success: (res: any) => {
          console.log('获取用户信息成功');
          // 可以将 res 发送给后台解码出 unionId
          this.globalData.userInfo = res.userInfo;
          wx.setStorageSync('userinfo', this.globalData.userInfo);
          this.getSession3rd();
        }
      })
    } else {
      console.log('没有授权,需要在界面上授权');
      wx.switchTab({
        url: '/pages/my/my'
      })
    }
  })

kingyo 2020-11-03
  • 打赏
  • 举报
回复
多谢泡泡鱼的热心解惑。 我这个是微信小程序的一个登录,原来用的是回调版本的, wx.getSetting如果成功调用success回调,失败调用failed回调, 成功之后,会调用wx.getUserInfo,也是成功调用sucess回调,这个回调里有一个if-else

        wx.getSetting({
            success: res => {
                if (res.authSetting['scope.userInfo']) {
                    console.log('已经授权,可以直接获取头像昵称');
                    // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
                    wx.getUserInfo({
                        success: res => {
                            console.log('获取用户信息成功');
                            // 可以将 res 发送给后台解码出 unionId
                            this.globalData.userInfo = res.userInfo;
                            wx.setStorageSync('userinfo', this.globalData.userInfo);
                            this.getSession3rd();
                        }
                    })
                } else {
                    console.log('没有授权,需要在界面上授权');
                    wx.switchTab({
                        url: '/pages/my/my',
                    });
                }
            }
        })
然后我要改成promise风格, 假设wxp是wx的promise化后的,调用时就不用回调了

        wxp.getSetting().then(res => {
            if (res.authSetting['scope.userInfo']) {
                console.log('已经授权,可以直接获取头像昵称');
                // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
                return wxp.getUserInfo();
            } else {
                console.log('没有授权,需要在界面上授权');
                return wxp.switchTab({
                    url: '/pages/my/my',
                });
            }
        }).then(res => {
            //像这种回调,怎么知道返回的是wxp.getUserInfo()还是wxp.switchTab()?  《====
            console.log('获取用户信息成功');
            // 可以将 res 发送给后台解码出 unionId
            this.globalData.userInfo = res.userInfo;
            wx.setStorageSync('userinfo', this.globalData.userInfo);
            this.getSession3rd();
        })
我不知道这种写法或者理解是否正确
泡泡鱼_ 2020-11-03
  • 打赏
  • 举报
回复
我们简单的模拟一下吧

function funA(a: any) {
  return new Promise(function(resolve, reject) {
    if(a < 3) {
      resolve(a);
    } else {
      reject(a);
    }
  })
}
function funIf() {

}

function funElse() {

}
funA(1).then(res => {
  return res === 1 ? funIf() : funElse()
}).then(res => {
  console.log(res);//undefined
});
你上面说过“业务上两个函数不返回任何东西。或者这是第三方函数,不返回任何东西”。那我就最干脆的把funIf和funElse搞成一个空函数了。 结果不用看,肯定在后面的then中res是undefined的。因为不论是funIf还是funElse它们本身并不返回Promise的某个结果 然后我们再换过一种模拟

function funA(a: any) {
  return new Promise(function(resolve, reject) {
    if(a < 3) {
      resolve(a);
    } else {
      reject(a);
    }
  })
}
function funIf(res: any) {
  return new Promise(function(resolve, reject) {
    if(res === 1) {
      resolve('in if');
    } else {
      reject(res);
    }
  })
}

function funElse(res: any) {
  return new Promise(function(resolve, reject) {
    if(res === 2) {
      resolve('in else');
    } else {
      reject(res);
    }
  })
}
funA(2).then(res => {
  return res ===1 ? funIf(res) : funElse(res)
}).then(res => {
  console.log(res)
});

这次不同了,funIf和funElse都是基于Promise的。 调用时,第二个then中。res的值必然是在funIf或funElse中resolve过来的值。我这里图个方便,我在funA中,对参数a做了个最简单的区分,然后在then中按值去返回funIf或funElse; 那么 funA(1).then().then() => in if funA(2).then().then() => in else 当然这是简单模拟,但这说明了。不论是你说的funIf还是funElse。它本身都是要resolve。才能进入下一流程 当然,你在它们里面可以resolve()。就没有具体的值。但你既然没有值到下一个流程去。你第二个then的必要性在哪? 因为以你的流程,你在funIf或funElse中就已经把事情做完了呀。你只需要在它们异常时reject一个Error出去,下一流程中可以用catch捕捉到就行了吧??? 然后,换过一种模拟,funIf和funElse按你说的,没有任何返回值,那应该就只有你人为的,额外的给出一个值吧?否则还能如何区分?

function funA(a: any) {
  return new Promise(function(resolve, reject) {
    if(a < 3) {
      resolve(a);
    } else {
      reject(a);
    }
  })
}
function funIf() {
  return new Promise(function(resolve, reject) {
    resolve();
  })
}

function funElse() {
  return new Promise(function(resolve, reject) {
    resolve();
  })
}

function command(fn: Function, state: any) {
  return new Promise(function(resolve, reject) {
    fn();
    resolve(state);
  })
}
funA(2).then(res => {
  return command(res === 1 ? funIf : funElse, res);
}).then(res => {
  console.log(res)
});
或者,你把你的代码贴出来看看?
kingyo 2020-11-03
  • 打赏
  • 举报
回复
引用 2 楼 泡泡鱼_ 的回复:
真要有这种需求,最简单的就是在你上面的return if or else时,额外定义或附加一个状态标识。
引用 1 楼 落落叶叶无声 的回复:

funA().then(res => {
  if (res)
    return funIf();  //if分支的Promise
  else
    return funElse(); //else分支的Promise
}).then((previousReturn) => { // <======
  //这里我怎么知道是哪个分支过来的?
  console.log('in if or else?', previousReturn); // 上个 then return 的值会在下个 then 里获取到,可以根据这个来判断
});
业务上两个函数不返回任何东西。或者这是第三方函数,不返回任何东西。那么还能如何区分?简单的使用额外的一个状态标志当然可以的。我只是想有没有更加合适的方式分辨。
泡泡鱼_ 2020-11-02
  • 打赏
  • 举报
回复
真要有这种需求,最简单的就是在你上面的return if or else时,额外定义或附加一个状态标识。
落落叶叶无声 2020-11-02
  • 打赏
  • 举报
回复

funA().then(res => {
  if (res)
    return funIf();  //if分支的Promise
  else
    return funElse(); //else分支的Promise
}).then((previousReturn) => { // <======
  //这里我怎么知道是哪个分支过来的?
  console.log('in if or else?', previousReturn); // 上个 then return 的值会在下个 then 里获取到,可以根据这个来判断
});

87,907

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧