中断“切换”将打破两个层次

时间:2018-09-30 13:10:10

标签: javascript react-native babeljs

我使用的是Babel 7的RN 0.57.1​​。但这只是一个“ javascript”问题。

我还无法繁殖(即使与另一个开关块处于同一循环中)也已经整天工作了。我将继续通过调查已转译的代码来解决这个问题。但是出于某些奇怪的原因,break中的switch语句中断了父while循环。我不得不用break PUSH_KIND_SWITCH代替它们。如果我使用常规的break会导致问题。我只是在这里发布,如果有人在我继续调查的过程中发现任何错误:

未翻译的代码:

function* pushWorker(message: PushMessage, accountId: AccountId, calendarId: CalendarId): Generator<*, void, *> {

    // if no channel for this id, create a channel for it
    const accCalId = buildAccCalId(accountId, calendarId);
    // console.log('in pushWorker, message:', message);
    const { id } = message;

    let buf, chan;
    {
        const { id } = message;
        if (pushChanById.hasOwnProperty(id)) {
            console.log('channel already in pushChanById, will put to it, id:', id);
            pushChanById[id].put(message);
            return;
        } else {
            console.log('creating channel');
            buf = buffers.expanding(1)
            pushChanById[id] = yield call(channel, buf);
            // pushChanById[id].put(message);
        }

        chan = pushChanById[id];
    }

    // console.log('material for id:', id, 'buf:', buf, 'chan:', chan);

    PUSH_MESSAGE_LOOP:
    while (true) {
        console.log('at top of while-loop for saga for event id:', id);
        console.log('got message in chan, message:', message, 'will check newerMessages (which are newer then this current message) to see if this newer should cancel & ovveride this message');

        console.log('will delay 5s to allow user to batch actions - for instance undo is allowed for 4sec, so that would cancel the create');
        yield call(delay, 5000);
        console.log('done delay');

        // remove all newer messages in channel, and boil it down to one message to act on
        const newerMessages = yield flush(chan);
        console.log('newerMessages in chan:', newerMessages, 'recall that current message is:', message);

        message = newerMessages.last || message;
        console.log('checked newerMessages, and decided message to act on is:', message);

        // act on message
        let { kind } = message;
        let event = yield select(selectEvent, id);

        if (!event) {
            console.warn('EVENT NO LONGER EXISTS, so disccarding, and skipping switch block and skip to kill the channel this SHOULD NEVER HAPPEN');
        } else {

            const meta = getPushMeta(event, accountId, calendarId);
            const isRemoteExisting = meta.sid !== undefined;
            if (kind === PK.create && isRemoteExisting) {
                console.log('kind was create, but isRemoteExisting, so change this to update!');
                kind = PK.update;
            } else if (kind === PK.update && !isRemoteExisting) {
                console.log('kind was update, but isRemoteExisting is false!!, so change this to create!');
                kind = PK.create;
            }

            PUSH_KIND_SWITCH:
            switch (kind) {
                case PK.delete: {
                        const calendar = (yield select(selectActiveCalendar)) || { id:'primary' };
                        const calendarId = calendar.id;
                        const remoteEventId = meta.sid; // if !isRemoteExisting then this will be undefined

                        let status;
                        if (isRemoteExisting) {
                            ({ status } = yield call(
                                fetch,
                                `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/${remoteEventId}`,
                                {
                                    method: 'delete'
                                }
                            ));
                        }

                        if (!isRemoteExisting || status === 204 || status === 410) {
                            // 410 - P error:{ code:410, errors:[...], message:'Resource has been delete' }

                            yield put(patchEvent(id, {
                                pushMetaByAccCalId: {
                                    [accCalId]: {
                                        accCalId,
                                        accountId,
                                        calendarId,
                                        sid: undefined,
                                        version: event.version
                                    }
                                }
                            }));

                            // TODO: think about also making sure there are no more messages, probably with a buf.isEmpty(), cuz what if another came in to undo it?
                            // check if deleted from all other accounts, if so then _deleteEvent
                            const otherMetas = Object.values(event.pushMetaByAccCalId || {}).filter(meta => meta.accCalId !== accCalId); // remove this account, as we know for sure it was pushed. no need to do a `yield select()`
                            const isLatestRemoteExistOnAllAccounts = otherMetas.every(otherMeta => [undefined, event.version].includes(otherMeta.version)); // undefined because latest remote is a deleted, so if others are undefined great it never got anything
                            event = yield select(selectEvent, id);
                            if (isLatestRemoteExistOnAllAccounts && !testIfRecording(event)) yield put(_deleteEvent(id));
                        } else {
                            console.warn('failed to delete, i should keep retrying this, until another message comes in to chan canceling this one?');
                        }
                    break;
                }
                case PK.create: {
                        const calendar = (yield select(selectActiveCalendar)) || { id:'primary' };
                        const calendarId = calendar.id;

                        const { title, summary } = extractTitleAndSummary(event.memo);

                        const { reply, status } = yield call(
                            fetch,
                            `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events`,
                            {
                                method: 'post',
                                body: {
                                    summary: title,
                                    description: summary,
                                    start: {
                                        dateTime: moment(event.start).toISOString()
                                    },
                                    end: {
                                        dateTime: moment(event.end).toISOString()
                                    },
                                    location: event.location
                                }
                            }
                        );

                        if (status === 200) {
                            yield put(patchEvent(id, {
                                pushMetaByAccCalId: {
                                    [accCalId]: {
                                        accCalId,
                                        accountId,
                                        calendarId,
                                        sid: reply.id,
                                        version: event.version
                                    }
                                }
                            }));
                        } else {
                            console.warn('failed to insert event, i should keep retrying this, until another message comes in to chan canceling this one?');
                        }
                    break;
                }
                case PK.update: {
                        const calendarId = get(yield select(), ['prefs', 'calendar', 'id'], 'primary');
                        const remoteEventId = meta.sid;

                        const { title, summary } = extractTitleAndSummary(event.memo);

                        const { reply, status } = yield call(
                            fetch,
                            `https://www.googleapis.com/calendar/v3/calendars/${calendarId}/events/${remoteEventId}`,
                            {
                                method: 'put',
                                body: {
                                    summary: title,
                                    description: summary,
                                    start: {
                                        dateTime: moment(event.start).toISOString()
                                    },
                                    end: {
                                        dateTime: moment(event.end).toISOString()
                                    },
                                    location: event.location
                                }
                            }
                        );

                        if (status === 200) {
                            yield put(patchEvent(id, {
                                pushMetaByAccCalId: {
                                    [accCalId]: {
                                        accCalId,
                                        accountId,
                                        calendarId,
                                        sid: reply.id,
                                        version: event.version
                                    }
                                }
                            }));
                        } else {
                            console.warn('failed to update event, i should keep retrying this, until another message comes in to chan canceling this one?');
                        }
                    break;
                }
            }
            // console.log('out of switch MUST SEE');
        }
        // console.log('out of if-else MUST SEE');

        // destroy channel if channel is empty, else continue the while loop to process next message
        if (buf.isEmpty()) {
            console.log('buf is empty for event id:', id, 'so destroying channel and quiting pushSaga for it');
            chan.close();
            delete pushChanById[id];

            yield put(patchEvent(id, { status:undefined })); // set status to undefined, as push is complete. if event is deleted, it just wont do anything
            break PUSH_MESSAGE_LOOP;
        } else {
            console.log('at bottom of while-loop, and there are more messages so immediately take next message, for saga for event id:', id);
            message = yield take(chan);
            console.log('got another message from chan while at bottom, message:', message);
        }
    }
    // console.log('out of while if did not see 2x "MUST SEE" this is a bug');
}

传票代码

  function pushWorker(message, accountId, calendarId) {
    var accCalId, _message, id, buf, chan, _message2, _id, _loop, _ret;

    return _regenerator.default.wrap(function pushWorker$(_context14) {
      while (1) {
        switch (_context14.prev = _context14.next) {
          case 0:
            accCalId = (0, _utils2.buildAccCalId)(accountId, calendarId);
            _message = message, id = _message.id;
            _message2 = message, _id = _message2.id;

            if (!pushChanById.hasOwnProperty(_id)) {
              _context14.next = 9;
              break;
            }

            console.log('channel already in pushChanById, will put to it, id:', _id);

            pushChanById[_id].put(message);

            return _context14.abrupt("return");

          case 9:
            console.log('creating channel');
            buf = _reduxSaga.buffers.expanding(1);
            _context14.next = 13;
            return (0, _effects.call)(_reduxSaga.channel, buf);

          case 13:
            pushChanById[_id] = _context14.sent;

          case 14:
            chan = pushChanById[_id];
            _loop = _regenerator.default.mark(function _loop() {
              var newerMessages, _message3, kind, event, meta, isRemoteExisting, calendar, _calendarId, remoteEventId, status, _ref10, otherMetas, isLatestRemoteExistOnAllAccounts, _calendar, _calendarId2, _extractTitleAndSumma, title, summary, _ref11, reply, _status, _calendarId3, _remoteEventId, _extractTitleAndSumma2, _title, _summary, _ref12, _reply, _status2;

              return _regenerator.default.wrap(function _loop$(_context13) {
                while (1) {
                  switch (_context13.prev = _context13.next) {
                    case 0:
                      console.log('at top of while-loop for saga for event id:', id);
                      console.log('got message in chan, message:', message, 'will check newerMessages (which are newer then this current message) to see if this newer should cancel & ovveride this message');
                      console.log('will delay 5s to allow user to batch actions - for instance undo is allowed for 4sec, so that would cancel the create');
                      _context13.next = 5;
                      return (0, _effects.call)(_reduxSaga.delay, 5000);

                    case 5:
                      console.log('done delay');
                      _context13.next = 8;
                      return (0, _effects.flush)(chan);

                    case 8:
                      newerMessages = _context13.sent;
                      console.log('newerMessages in chan:', newerMessages, 'recall that current message is:', message);
                      message = newerMessages.last || message;
                      console.log('checked newerMessages, and decided message to act on is:', message);
                      _message3 = message, kind = _message3.kind;
                      _context13.next = 15;
                      return (0, _effects.select)(_selectors.selectEvent, id);

                    case 15:
                      event = _context13.sent;

                      if (event) {
                        _context13.next = 20;
                        break;
                      }

                      console.warn('EVENT NO LONGER EXISTS, so disccarding, and skipping switch block and skip to kill the channel this SHOULD NEVER HAPPEN');
                      _context13.next = 94;
                      break;

                    case 20:
                      meta = (0, _utils2.getPushMeta)(event, accountId, calendarId);
                      isRemoteExisting = meta.sid !== undefined;

                      if (kind === PK.create && isRemoteExisting) {
                        console.log('kind was create, but isRemoteExisting, so change this to update!');
                        kind = PK.update;
                      } else if (kind === PK.update && !isRemoteExisting) {
                        console.log('kind was update, but isRemoteExisting is false!!, so change this to create!');
                        kind = PK.create;
                      }

                      _context13.t0 = kind;
                      _context13.next = _context13.t0 === PK.delete ? 26 : _context13.t0 === PK.create ? 54 : _context13.t0 === PK.update ? 74 : 94;
                      break;

                    case 26:
                      _context13.next = 28;
                      return (0, _effects.select)(_selectors2.selectActiveCalendar);

                    case 28:
                      _context13.t1 = _context13.sent;

                      if (_context13.t1) {
                        _context13.next = 31;
                        break;
                      }

                      _context13.t1 = {
                        id: 'primary'
                      };

                    case 31:
                      calendar = _context13.t1;
                      _calendarId = calendar.id;
                      remoteEventId = meta.sid;

                      if (!isRemoteExisting) {
                        _context13.next = 39;
                        break;
                      }

                      _context13.next = 37;
                      return (0, _effects.call)(_fetch.default, "https://www.googleapis.com/calendar/v3/calendars/" + _calendarId + "/events/" + remoteEventId, {
                        method: 'delete'
                      });

                    case 37:
                      _ref10 = _context13.sent;
                      status = _ref10.status;

                    case 39:
                      if (!(!isRemoteExisting || status === 204 || status === 410)) {
                        _context13.next = 52;
                        break;
                      }

                      _context13.next = 42;
                      return (0, _effects.put)(patchEvent(id, {
                        pushMetaByAccCalId: (0, _defineProperty2.default)({}, accCalId, {
                          accCalId: accCalId,
                          accountId: accountId,
                          calendarId: _calendarId,
                          sid: undefined,
                          version: event.version
                        })
                      }));

                    case 42:
                      otherMetas = Object.values(event.pushMetaByAccCalId || {}).filter(function (meta) {
                        return meta.accCalId !== accCalId;
                      });
                      isLatestRemoteExistOnAllAccounts = otherMetas.every(function (otherMeta) {
                        return [undefined, event.version].includes(otherMeta.version);
                      });
                      _context13.next = 46;
                      return (0, _effects.select)(_selectors.selectEvent, id);

                    case 46:
                      event = _context13.sent;

                      if (!(isLatestRemoteExistOnAllAccounts && !(0, _utils2.testIfRecording)(event))) {
                        _context13.next = 50;
                        break;
                      }

                      _context13.next = 50;
                      return (0, _effects.put)(_deleteEvent(id));

                    case 50:
                      _context13.next = 53;
                      break;

                    case 52:
                      console.warn('failed to delete, i should keep retrying this, until another message comes in to chan canceling this one?');

                    case 53:
                      return _context13.abrupt("return", "break");

                    case 54:
                      _context13.next = 56;
                      return (0, _effects.select)(_selectors2.selectActiveCalendar);

                    case 56:
                      _context13.t2 = _context13.sent;

                      if (_context13.t2) {
                        _context13.next = 59;
                        break;
                      }

                      _context13.t2 = {
                        id: 'primary'
                      };

                    case 59:
                      _calendar = _context13.t2;
                      _calendarId2 = _calendar.id;
                      _extractTitleAndSumma = (0, _utils2.extractTitleAndSummary)(event.memo), title = _extractTitleAndSumma.title, summary = _extractTitleAndSumma.summary;
                      _context13.next = 64;
                      return (0, _effects.call)(_fetch.default, "https://www.googleapis.com/calendar/v3/calendars/" + _calendarId2 + "/events", {
                        method: 'post',
                        body: {
                          summary: title,
                          description: summary,
                          start: {
                            dateTime: (0, _moment.default)(event.start).toISOString()
                          },
                          end: {
                            dateTime: (0, _moment.default)(event.end).toISOString()
                          },
                          location: event.location
                        }
                      });

                    case 64:
                      _ref11 = _context13.sent;
                      reply = _ref11.reply;
                      _status = _ref11.status;

                      if (!(_status === 200)) {
                        _context13.next = 72;
                        break;
                      }

                      _context13.next = 70;
                      return (0, _effects.put)(patchEvent(id, {
                        pushMetaByAccCalId: (0, _defineProperty2.default)({}, accCalId, {
                          accCalId: accCalId,
                          accountId: accountId,
                          calendarId: _calendarId2,
                          sid: reply.id,
                          version: event.version
                        })
                      }));

                    case 70:
                      _context13.next = 73;
                      break;

                    case 72:
                      console.warn('failed to insert event, i should keep retrying this, until another message comes in to chan canceling this one?');

                    case 73:
                      return _context13.abrupt("return", "break");

                    case 74:
                      _context13.t3 = _lodash.get;
                      _context13.next = 77;
                      return (0, _effects.select)();

                    case 77:
                      _context13.t4 = _context13.sent;
                      _context13.t5 = ['prefs', 'calendar', 'id'];
                      _calendarId3 = (0, _context13.t3)(_context13.t4, _context13.t5, 'primary');
                      _remoteEventId = meta.sid;
                      _extractTitleAndSumma2 = (0, _utils2.extractTitleAndSummary)(event.memo), _title = _extractTitleAndSumma2.title, _summary = _extractTitleAndSumma2.summary;
                      _context13.next = 84;
                      return (0, _effects.call)(_fetch.default, "https://www.googleapis.com/calendar/v3/calendars/" + _calendarId3 + "/events/" + _remoteEventId, {
                        method: 'put',
                        body: {
                          summary: _title,
                          description: _summary,
                          start: {
                            dateTime: (0, _moment.default)(event.start).toISOString()
                          },
                          end: {
                            dateTime: (0, _moment.default)(event.end).toISOString()
                          },
                          location: event.location
                        }
                      });

                    case 84:
                      _ref12 = _context13.sent;
                      _reply = _ref12.reply;
                      _status2 = _ref12.status;

                      if (!(_status2 === 200)) {
                        _context13.next = 92;
                        break;
                      }

                      _context13.next = 90;
                      return (0, _effects.put)(patchEvent(id, {
                        pushMetaByAccCalId: (0, _defineProperty2.default)({}, accCalId, {
                          accCalId: accCalId,
                          accountId: accountId,
                          calendarId: _calendarId3,
                          sid: _reply.id,
                          version: event.version
                        })
                      }));

                    case 90:
                      _context13.next = 93;
                      break;

                    case 92:
                      console.warn('failed to update event, i should keep retrying this, until another message comes in to chan canceling this one?');

                    case 93:
                      return _context13.abrupt("return", "break");

                    case 94:
                      if (!buf.isEmpty()) {
                        _context13.next = 103;
                        break;
                      }

                      console.log('buf is empty for event id:', id, 'so destroying channel and quiting pushSaga for it');
                      chan.close();
                      delete pushChanById[id];
                      _context13.next = 100;
                      return (0, _effects.put)(patchEvent(id, {
                        status: undefined
                      }));

                    case 100:
                      return _context13.abrupt("return", "break|PUSH_MESSAGE_LOOP");

                    case 103:
                      console.log('at bottom of while-loop, and there are more messages so immediately take next message, for saga for event id:', id);
                      _context13.next = 106;
                      return (0, _effects.take)(chan);

                    case 106:
                      message = _context13.sent;
                      console.log('got another message from chan while at bottom, message:', message);

                    case 108:
                    case "end":
                      return _context13.stop();
                  }
                }
              }, _loop, this);
            });

          case 16:
            if (!true) {
              _context14.next = 26;
              break;
            }

            return _context14.delegateYield(_loop(), "t0", 18);

          case 18:
            _ret = _context14.t0;
            _context14.t1 = _ret;
            _context14.next = _context14.t1 === "break" ? 22 : _context14.t1 === "break|PUSH_MESSAGE_LOOP" ? 23 : 24;
            break;

          case 22:
            return _context14.abrupt("break", 26);

          case 23:
            return _context14.abrupt("break", 26);

          case 24:
            _context14.next = 16;
            break;

          case 26:
          case "end":
            return _context14.stop();
        }
      }
    }, _marked13, this);
  }

0 个答案:

没有答案