Mengakses kontak Google saat masuk pengguna menimbulkan kesalahan Meteor.bindEnvironment. Apa yang salah dengan pemahaman saya tentang serat di sini?

Jawabannya di - "Apa yang terjadi dengan Meteor dan Fibers/bindEnvironment() ?" sangat membantu namun tidak dapat membantu menyelesaikan masalah saya.

Inilah yang saya lakukan:

  1. Masuk dengan google
  2. Hubungi FunGoogle(pengguna) dari Accounts.onCreateUser

kode:

SocialFunGoogle = function (user) {
  var config = Accounts.loginServiceConfiguration.findOne({service: 'google'});

  var opts = {
    consumerKey: config.clientId,
    consumerSecret: config.secret,
    token: user.services.google.accessToken,
    refreshToken: user.services.google.refreshToken
  };
  var gcontacts = new GoogleContacts(opts);

  gcontacts.refreshAccessToken(opts.refreshToken, function (err, accessToken) {
    if (err && err != null) {
      console.log('gcontact.refreshToken, ', err);
      return false;
    } else {
      console.log('gcontact.access token success!');
      gcontacts.token = accessToken;
    }
  });

  var fn = Meteor.bindEnvironment(function () {
    var Fiber = Meteor.require('fibers');
    var Future = Meteor.require('fibers/future');
    var future = new Future();
    setTimeout(function () {
      return future.return(
        Fiber(function () {
          gcontacts.getContacts(
            function (err, contact) {
              contact = [{
                name: 'S Sharma',
                email: '[email protected]',
                photoUrl: 'https://www.google.com/m8/feeds/photos/media/procrazium%40gmail.com/adf456aaaabbnndaa',
                mime_type: 'image/*'
              }, {
                name: 'A Kapil',
                email: '[email protected]',
                photoUrl: 'https://www.google.com/m8/feeds/photos/media/procrazium%40gmail.com/22aaaab555758bc37952',
                mime_type: 'image/*'
              }, {
                name: 'A Kartik',
                email: '[email protected]',
                photoUrl: 'https://www.google.com/m8/feeds/photos/media/procrazium%40gmail.com/2f2aaa02aab00f7aa85a2',
                mime_type: 'image/*'
              }];

              contact.map(function (c) {
                SocialConnect.insert(c);
              });

              return contact;
            });
        }).run()
      );
    }, 500);
  });

  fn();
}

Saat saya mencoba masuk, kode saya memunculkan kesalahan berikut.

  1. Pengecualian saat menjalankan metode 'login' TypeError: Tidak dapat menyetel properti '_meteor_dynamics' yang tidak ditentukan

  2. Kesalahan: Kode meteor harus selalu dijalankan dalam Fiber. Coba gabungkan callback yang Anda teruskan ke perpustakaan non-Meteor dengan Meteor.bindEnvironment

Bisakah Anda menunjukkan kesalahan apa yang saya lakukan di sini?


person procrazium    schedule 22.05.2014    source sumber


Jawaban (1)


gcontacts.refreshAccessToken(opts.refreshToken, function (err, accessToken) {
  // B
  if (err && err != null) {
    console.log('gcontact.refreshToken, ', err);
    return false; // C
  } else {
    console.log('gcontact.access token success!');
    gcontacts.token = accessToken;
  }
});
// A

Ini bukan cara yang benar untuk melakukan async di JavaScript:

  • SocialFunGoogle mencapai // A sebelum kode di // B dijalankan, jadi tidak ada jaminan bahwa gcontacts.token telah disetel. (Mungkin itulah gunanya batas waktu, tapi itu tidak dapat diandalkan karena fungsinya akan gagal secara misterius jika penyegaran token memerlukan waktu lebih dari 500 md.)
  • return di // C kembali dari fungsi panggilan balik anonim, bukan dari SocialFunGoogle, jadi ini tidak akan menghasilkan apa yang Anda inginkan.

Biasanya Anda harus menyarangkan sisa fungsi Anda ke dalam panggilan balik ini, tetapi Meteor menggunakan Fibers, jadi Anda tidak perlu melakukannya. Fibers memungkinkan Anda menulis kode seolah-olah sinkron, namun di balik layar, kode tersebut masih berjalan secara asinkron seperti aplikasi node.js lainnya.

Sayangnya sebagian besar paket npm ditulis untuk gaya panggilan balik, namun ada cara sederhana untuk mengadaptasi kode panggilan balik untuk Fibers. Saya akan menggunakan Futures. Inilah cara Anda dapat menulis ulang kode tersebut menggunakan Futures:

var future = new Future(); // 1

gcontacts.refreshAccessToken(opts.refreshToken, function (err, accessToken) { //2
  future["return"]({err: err, accessToken: accessToken}); // 4
});

var result = future.wait(); // 3, 5
if (result.err && result.err != null) { // 6
  console.log('gcontact.refreshToken, ', result.err);
  return false;
} else {
  console.log('gcontact.access token success!');
  gcontacts.token = result.accessToken;
}

Begini cara pelaksanaannya:

  1. Kita menciptakan Masa Depan baru yang belum terselesaikan.
  2. Kami menjalankan tindakan asinkron.
  3. Sementara tindakan asinkron masih terjadi, kami wait() berada di Masa Depan. Fiber saat ini tertidur, menunggu Masa Depan terselesaikan.
  4. Tindakan asinkron selesai. Dalam panggilan balik untuk tindakan async tersebut, kami menyelesaikan Masa Depan menggunakan metode return-nya.
  5. Karena Masa Depan terselesaikan, Fiber terbangun, dan objek yang kita lewati ke future.return muncul dari future.wait.
  6. Fungsi tetap berjalan seperti biasa.

Anda juga dapat menggunakan pola ini untuk menangani panggilan getContacts. Karena satu-satunya kode yang berjalan di luar Fiber adalah panggilan future.return, Anda tidak perlu bindEnvironment atau membuat Fiber Anda sendiri.

person user3374348    schedule 23.05.2014