【讨论】这个 Promise 模块该怎么写?
发布于 2 个月前 作者 nswbmw 1001 次浏览 最后一次编辑是 1 个月前 来自 分享

今天想写一个模块,但没写出来,所以贴出来集思广益。

目标解决:有时候需要在 Promise 表达式外定义一个变量存储某一步 .then 的结果,比如第三个 .then 里面取不到第一个 .then 的结果。

最终效果:

Promise.resolve(1)
  .then(function(a) {
    // a === 1
    return Promise.resolve(2)
      .then(function(b) {
        // b === 2
        return 3
      })
      .then(function(c, d) {
        // c === 3
        // d === 2
        return 4
      })
  })
  .then(function(e, f) {
    // e === 4
    // f === 1
  })

可以看出:同一层的 .then 的参数是之前所有 .then 结果的逆序,里层的 .then 最后的结果返回到上层的 .then(跟原生用法一样)。

有以下几点要求:

  1. 以上 Promise.resolve 可以换成其他的如:Promise.all 等等
  2. hack 原生 Promise,最好第三方 Promise 库也支持,如:bluebird,而不是实现一个新的 Promise
  3. .catch 不变

我的思路:

每个 Promise 实例(以 promise 代称)会生成一个随机 _id(不同层的 promise 的 _id 不同),用 _results 存储(unshift)每一步 .then 的结果,最后 apply 一下。但后来发现我的做法的前提是认为同层的 promise 的 .then 的链式调用是同一个 Promise 实例,然而并不是,每一个 .then 都会生成一个新的 Promise 实例,所以此路不通。

上述思路的测试代码:

const shortid = require('shortid');

class myPromise extends Promise {
  constructor(fn) {
    super(fn);
    this._id = shortid.generate();
    this._results = [];
  }
}


const a = myPromise.resolve(1);
console.log(a._id);
console.log(a.then(() => 2)._id);
console.log(a.then(() => 2).then(() => 3)._id);

所以。元芳,你怎么看?

10 回复
return new Promise(function(resolve, reject) {
    var result = [];
    resolve(result);
})

Promise 只是个简单载体, 研究深了会吐…设计的不好, 直接拿 .NET System.Threading.Task copy 过来多好

以下3个替代方案可以考虑吗

  1. co或者bluebird的coroutine
  2. async/await
  3. async.js的auto

@qingfeng

  1. 纯用 Promise
  2. 同上
  3. 不用 callback

这个 promise 模块如果按这么写的话,会不会违反 promise 对于 then 的参数的约定?如果违反了的话,带来的便利不及它的混乱和难上手程度吧?

@alsotang 纯用promise就是作死

我现在 在学习 async &await 直接跳过 .then 因为我看不懂,😄小白伤不起,希望到某天我成大神了,也能和你们一起讨论,学了快一学期的编程了感觉编程还挺爽。还有两年我就要毕业了,我该抓紧了。

Promise不是你这么用的吧? 实际是这样的,有任务A、B 和 C,C 依赖A 和B 的结果

var A = Promise.resolve({a:1}); // 任务A
var B = Promise.resolve({b:2}); // 任务B
Promise.all([A,B]).then(function({a,b}){
    // 任务C
    console.log(a,b);
});

如有任务A、B 、C和 F,F 依赖A 和D 的结果,而C 依赖于B的结果

var A = Promise.resolve({a:1}); // 任务A
var C = Promise.resolve({b:2})  // 任务B
    .then(()=>Promise.resolve({c:1})); // 任务C
Promise.all([A,C]).then(function({a,b}){
    // 任务D
    console.log(a,b);
});

或者根本就是一个串行的,可以直接传递一个 stat对象,用来表示状态,直接对 stat操作就行不用另外保存状态,传递的stat 对象就表明了状态

你可以理解为描述了一种依赖关系

@Shonke 我只想单纯的讨论如何实现这个功能,不讨论 Promise 的使用姿势

对于每个then return出来的都是新的promise 你怎么去判断他是下一层的promise呢 promise的使用姿势不对

回到顶部