333
schangxiang@126.com
2025-09-19 18966e02fb573c7e2bb0c6426ed792b38b910940
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
 
const proto = exports;
 
proto._parallelNode = async function _parallelNode(todo, parallel, fn, sourceData) {
  const that = this;
  // upload in parallel
  const jobErr = [];
  let jobs = [];
  const tempBatch = todo.length / parallel;
  const remainder = todo.length % parallel;
  const batch = remainder === 0 ? tempBatch : ((todo.length - remainder) / parallel) + 1;
  let taskIndex = 1;
  for (let i = 0; i < todo.length; i++) {
    if (that.isCancel()) {
      break;
    }
 
    if (sourceData) {
      jobs.push(fn(that, todo[i], sourceData));
    } else {
      jobs.push(fn(that, todo[i]));
    }
 
    if (jobs.length === parallel || (taskIndex === batch && i === (todo.length - 1))) {
      try {
        taskIndex += 1;
        /* eslint no-await-in-loop: [0] */
        await Promise.all(jobs);
      } catch (err) {
        jobErr.push(err);
      }
      jobs = [];
    }
  }
 
  return jobErr;
};
 
proto._parallel = function _parallel(todo, parallel, jobPromise) {
  const that = this;
  return new Promise((resolve) => {
    const _jobErr = [];
    if (parallel <= 0 || !todo) {
      resolve(_jobErr);
      return;
    }
 
    function onlyOnce(fn) {
      return function (...args) {
        if (fn === null) throw new Error('Callback was already called.');
        const callFn = fn;
        fn = null;
        callFn.apply(this, args);
      };
    }
 
    function createArrayIterator(coll) {
      let i = -1;
      const len = coll.length;
      return function next() {
        return (++i < len && !that.isCancel()) ? { value: coll[i], key: i } : null;
      };
    }
 
    const nextElem = createArrayIterator(todo);
    let done = false;
    let running = 0;
    let looping = false;
 
    function iterateeCallback(err, value) {
      running -= 1;
      if (err) {
        done = true;
        _jobErr.push(err);
        resolve(_jobErr);
      } else if (value === {} || (done && running <= 0)) {
        done = true;
        resolve(_jobErr);
      } else if (!looping) {
        /* eslint no-use-before-define: [0] */
        if (that.isCancel()) {
          resolve(_jobErr);
        } else {
          replenish();
        }
      }
    }
 
    function iteratee(value, callback) {
      jobPromise(value).then((result) => {
        callback(null, result);
      }).catch((err) => {
        callback(err);
      });
    }
 
    function replenish() {
      looping = true;
      while (running < parallel && !done && !that.isCancel()) {
        const elem = nextElem();
        if (elem === null || _jobErr.length > 0) {
          done = true;
          if (running <= 0) {
            resolve(_jobErr);
          }
          return;
        }
        running += 1;
        iteratee(elem.value, onlyOnce(iterateeCallback));
      }
      looping = false;
    }
 
    replenish();
  });
};
 
/**
 * cancel operation, now can use with multipartUpload
 * @param {Object} abort
 *        {String} anort.name object key
 *        {String} anort.uploadId upload id
 *        {String} anort.options timeout
 */
proto.cancel = function cancel(abort) {
  this.options.cancelFlag = true;
  if (abort) {
    this.abortMultipartUpload(abort.name, abort.uploadId, abort.options);
  }
};
 
proto.isCancel = function isCancel() {
  return this.options.cancelFlag;
};
 
proto.resetCancelFlag = function resetCancelFlag() {
  this.options.cancelFlag = false;
};
 
proto._stop = function _stop() {
  this.options.cancelFlag = true;
};
 
// cancel is not error , so create an object
proto._makeCancelEvent = function _makeCancelEvent() {
  const cancelEvent = {
    status: 0,
    name: 'cancel'
  };
  return cancelEvent;
};