1.Promise.all

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Promise.all = function(arr) {
var args = Array.prototype.slice.call(arr);
return new Promise(function(resolve, reject) {
if (args.length === 0) return resolve([]);
var remaining = args.length;
function res(i, val) {
try {
if (val && (typeof val === "object" || typeof val === "function")) {
var then = val.then;
if (typeof then === "function") {
then.call(val, function(val) {
// 对于thenable和promise对象则订阅onFulfilled事件获取处理结果值
res(i, val);
}, reject);
return; // 直接返回了 让val.then自己去执行
}
}
args[i] = val; // val在执行val.then之后会得到一个新的返回值 类似于function a(){ return new Promise(function(resolve,reject){})}
// 检测是否所有入参都已返回值
if (--remaining === 0) { // 每执行一次都会-1一次 直到为0
resolve(args);
}
} catch (ex) {
reject(ex);
}
}
for (var i = 0; i < args.length; i++) {
res(i, args[i]);
}
});
};

2.Promise 源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
function Promise(executor) {
let self = this
this.status = 'pending' //当前状态
this.value = undefined //存储成功的值
this.reason = undefined //存储失败的原因
this.onResolvedCallbacks = []//存储成功的回调
this.onRejectedCallbacks = []//存储失败的回调
function resolve(value) {
if (self.status == 'pending') {
self.status = 'resolved'
self.value = value
self.onResolvedCallbacks.forEach(fn => fn());
}
}
function reject(error) {
if (self.status == 'pending') {
self.status = 'rejected'
self.reason = error
self.onRejectedCallbacks.forEach(fn => fn())
}
}
try {
executor(resolve, reject)
} catch (error) {
reject(error)
}
}
Promise.prototype.then = function (infulfilled, inrejected) {
let self = this
let promise2
infulfilled = typeof infulfilled === 'function' ? infulfilled : function (val) {
return val
}
inrejected = typeof inrejected === 'function' ? inrejected : function (err) {
throw err
}
if (this.status == 'resolved') {
promise2 = new Promise(function (resolve, reject) {
//x可能是一个promise,也可能是个普通值
setTimeout(function () {
try {
let x = infulfilled(self.value)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
});

})
}
if (this.status == 'rejected') {

promise2 = new Promise(function (resolve, reject) {
//x可能是一个promise,也可能是个普通值
setTimeout(function () {
try {
let x = inrejected(self.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
});
})
}
if (this.status == 'pending') {
promise2 = new Promise(function (resolve, reject) {
self.onResolvedCallbacks.push(function () {
//x可能是一个promise,也可能是个普通值
setTimeout(function () {
try {
let x = infulfilled(self.value)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
});
})
self.onRejectedCallbacks.push(function () {
//x可能是一个promise,也可能是个普通值
setTimeout(function () {
try {
let x = inrejected(self.reason)
resolvePromise(promise2, x, resolve, reject)
} catch (err) {
reject(err)
}
});
})
})
}
return promise2
}
function resolvePromise(p2, x, resolve, reject) {
if (p2 === x && x != undefined) {
reject(new TypeError('类型错误'))
}
//可能是promise,看下对象中是否有then方法,如果有~那就是个promise
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {//为了防止出现 {then:11}这种情况,需要判断then是不是一个函数
let then = x.then
if (typeof then === 'function') {
then.call(x, function (y) {
//y 可能还是一个promise,那就再去解析,知道返回一个普通值为止
resolvePromise(p2, y, resolve, reject)
}, function (err) {
reject(err)
})
} else {//如果then不是function 那可能是对象或常量
resolve(x)
}
} catch (e) {
reject(e)
}
} else {//说明是一个普通值
resolve(x)
}
}

then返回的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
 Promise.resolve('foo')
  //第一个promise已经resolve,将'foo'传入第一个then。
  .then(function(string{
    return new Promise(function(resolve, reject{
      setTimeout(function({
        string += 'bar';
        resolve(string);
      }, 1000);//将1ms改为1s更易观察
    });
  })
//第一个then中的函数返回一个promise对象,该promise对象状态为pending,
//根据‘如果then中的回调函数返回一个未定状态(pending)的Promise,那么then返回Promise的状态也是未定的,
//并且它的终态与那个Promise的终态相同;同时,它变为终态时调用的回调函数参数与那个Promise变为终态时的回调函数的参数是相同的。 
//’摘自MDN。
//直到setTimeout时间到达,调用resolve(string),状态变为fulfilled(resolve),才调用下一个then方法。
  .then(function(string{
    setTimeout(function({
      string += 'baz';
      console.log(string);
    }, 1000)
    return string;
  })
//  在第二个then中,先调用setTimeout
//(估计题主的问题出在这里,setTimeout调用定时器后不会等待计时完成,而是继续执行下面的代码,
//  在1s的定时结束后再将其中的程序加入任务队列,不理解可以再看看关于MacroTask事件循环相关资料),
//  然后跳到return string,由于setTimeout内代码尚未执行,此时string == 'foobar'。
//   且根据 ‘如果then中的回调函数返回一个值,那么then返回的Promise将会成为接受状态,
//  并且将返回的值作为接受状态的回调函数的参数值。’摘自MDN。 
//  因此进入下一个then,且该段代码没有任何延时。
  .then(function(string{
    console.log("Last Then:  oops... didn't bother to instantiate and return " +
                "a promise in the prior then so the sequence may be a bit " +
                "surprising");
    console.log(string);
  });
  //由于第二个then中return的string值为'foobar',因此先输出'foobar'。
// 并在前面的1s定时结束后执行string += 'baz', 最后输出foobarbaz。

// Last Then:  oops..didn't bother to instantiate and return a promise in the prior then so the sequence may be a bit surprising
// foobar
// foobarbaz
← Prev Next →