Helpex - Trao đổi & giúp đỡ Đăng nhập
163

Mã của tôi:

let AuthUser = data => {
  return google.login(data.username, data.password).then(token => { return token } )
}

Và khi tôi cố gắng chạy một cái gì đó như thế này:

let userToken = AuthUser(data)
console.log(userToken)

Tôi nhận được:

Promise { <pending> }

Nhưng tại sao?

Mục tiêu chính của tôi là lấy mã thông báo google.login(data.username, data.password)mà từ đó trả về một lời hứa, thành một biến. Và chỉ sau đó thực hiện một số hành động.

163 hữu ích 5 bình luận 317k xem chia sẻ
236

Lời hứa sẽ luôn ghi nhật ký chờ xử lý miễn là kết quả của nó vẫn chưa được giải quyết. Bạn phải gọi .thenlời hứa để nắm bắt kết quả bất kể trạng thái lời hứa (đã giải quyết hay vẫn đang chờ xử lý):

let AuthUser = function(data) {
  return google.login(data.username, data.password).then(token => { return token } )
}

let userToken = AuthUser(data)
console.log(userToken) // Promise { <pending> }

userToken.then(function(result) {
   console.log(result) // "Some User token"
})

Tại sao vậy?

Những lời hứa chỉ là hướng về phía trước; Bạn chỉ có thể giải quyết chúng một lần. Giá trị đã phân giải của a Promiseđược chuyển cho .thenhoặc .catchcác phương thức của nó .

Chi tiết

Theo Promises / A + spec:

Thủ tục giải quyết lời hứa là một hoạt động trừu tượng lấy đầu vào là một lời hứa và một giá trị, mà chúng ta ký hiệu là [[Giải quyết]] (lời hứa, x). Nếu x là anable, nó cố gắng thực hiện lời hứa thông qua trạng thái của x, với giả thiết rằng x hoạt động ít nhất giống như một lời hứa. Nếu không, nó thực hiện lời hứa với giá trị x.

Việc xử lý các quyền này cho phép các triển khai hứa hẹn tương tác với nhau, miễn là chúng hiển thị phương thức sau đó tuân thủ Promises / A +. Nó cũng cho phép triển khai Promises / A + “đồng hóa” các triển khai không phù hợp với các phương pháp then hợp lý.

Thông số kỹ thuật này hơi khó để phân tích cú pháp, vì vậy hãy chia nhỏ nó. Quy tắc là:

Nếu hàm trong .thentrình xử lý trả về một giá trị, thì hàm Promisesẽ giải quyết với giá trị đó. Nếu trình xử lý trả về một giá trị khác Promise, thì bản gốc Promisesẽ phân giải với giá trị đã phân giải của chuỗi Promise. Trình .thenxử lý tiếp theo sẽ luôn chứa giá trị đã phân giải của lời hứa chuỗi được trả về ở phần trước .then.

Cách nó thực sự hoạt động được mô tả chi tiết hơn bên dưới:

1. Kết quả trả về của .thenhàm sẽ là giá trị được giải quyết của lời hứa.

function initPromise() {
  return new Promise(function(res, rej) {
    res("initResolve");
  })
}

initPromise()
  .then(function(result) {
    console.log(result); // "initResolve"
    return "normalReturn";
  })
  .then(function(result) {
    console.log(result); // "normalReturn"
  });

2. Nếu .thenhàm trả về a Promise, thì giá trị đã giải quyết của lời hứa chuỗi đó được chuyển đến giá trị sau .then.

function initPromise() {
  return new Promise(function(res, rej) {
    res("initResolve");
  })
}

initPromise()
  .then(function(result) {
    console.log(result); // "initResolve"
    return new Promise(function(resolve, reject) {
       setTimeout(function() {
          resolve("secondPromise");
       }, 1000)
    })
  })
  .then(function(result) {
    console.log(result); // "secondPromise"
  });
236 hữu ích 5 bình luận chia sẻ
30

Tôi biết câu hỏi này đã được hỏi cách đây 2 năm, nhưng tôi gặp phải vấn đề tương tự và câu trả lời cho vấn đề là kể từ ES2017, bạn có thể chỉ cần awaitcác hàm trả về giá trị (hiện tại, chỉ hoạt động trong các asynchàm), như:

let AuthUser = function(data) {
  return google.login(data.username, data.password).then(token => { return token } )
}

let userToken = await AuthUser(data)
console.log(userToken) // your data
30 hữu ích 5 bình luận chia sẻ
5

Các thenphương thức trả về một lời hứa cấp phát có thể được giải quyết đồng bộ bởi các giá trị trả về của một handler kết quả đăng ký trong các cuộc gọi đến then, hoặc từ chối bằng cách ném một lỗi bên trong xử lý gọi.

Vì vậy, việc gọi AuthUsersẽ không đột nhiên đăng nhập đồng bộ người dùng, nhưng trả về một lời hứa mà các trình xử lý đã đăng ký sau đó sẽ được gọi sau khi đăng nhập thành công (hoặc không thành công). Tôi sẽ đề nghị kích hoạt tất cả quá trình đăng nhập bằng một thenđiều khoản của lời hứa đăng nhập. EG sử dụng các hàm được đặt tên để làm nổi bật trình tự của luồng:

let AuthUser = data => {   // just the login promise
  return google.login(data.username, data.password);
};

AuthUser(data).then( processLogin).catch(loginFail);

function processLogin( token) {
      // do logged in stuff:
      // enable, initiate, or do things after login
}
function loginFail( err) {
      console.log("login failed: " + err);
}
5 hữu ích 0 bình luận chia sẻ
1

Xem phần MDN về Lời hứa. Đặc biệt, hãy nhìn vào kiểu trả về của then ().

Để đăng nhập, tác nhân người dùng phải gửi một yêu cầu đến máy chủ và đợi để nhận được phản hồi. Vì việc làm cho ứng dụng của bạn hoàn toàn ngừng thực thi trong khi yêu cầu khứ hồi thường tạo ra trải nghiệm người dùng không tốt, thực tế mọi hàm JS đăng nhập bạn (hoặc thực hiện bất kỳ hình thức tương tác máy chủ nào khác) sẽ sử dụng Promise hoặc một cái gì đó rất giống nó , để cung cấp kết quả không đồng bộ.

Bây giờ, cũng lưu ý rằng các returncâu lệnh luôn được đánh giá trong ngữ cảnh của hàm mà chúng xuất hiện. Vì vậy, khi bạn viết:

let AuthUser = data => {
  return google
    .login(data.username, data.password)
    .then( token => {
      return token;
    });
};

câu lệnh return token;có nghĩa là hàm ẩn danh được chuyển vào then()sẽ trả về mã thông báo, chứ không phải AuthUserhàm nên trả về. Những gì AuthUsertrả về là kết quả của việc gọi google.login(username, password).then(callback);, tình cờ là một Lời hứa.

Cuối cùng thì cuộc gọi lại của bạn token => { return token; }không làm gì cả; thay vào đó, đầu vào của bạn then()cần phải là một hàm thực sự xử lý mã thông báo theo một cách nào đó.

1 hữu ích 5 bình luận chia sẻ
0

Lời hứa của bạn đang chờ xử lý, hãy hoàn thành nó trước

userToken.then(function(result){
console.log(result)
})

sau mã còn lại của bạn. Tất cả những gì mã này làm là .then()hoàn thành lời hứa của bạn và ghi lại kết quả cuối cùng trong biến kết quả & in kết quả trong bảng điều khiển. Xin lưu ý rằng bạn không thể lưu trữ kết quả trong biến toàn cục. Hy vọng rằng lời giải thích có thể giúp bạn.

0 hữu ích 1 bình luận chia sẻ
0

Tôi đã gặp vấn đề tương tự trước đó, nhưng tình huống của tôi hơi khác ở giao diện người dùng. Dù sao thì tôi cũng sẽ chia sẻ kịch bản của mình, có thể ai đó sẽ thấy nó hữu ích.

Tôi đã có một cuộc gọi api /api/user/registertrong giao diện người dùng với email, mật khẩu và tên người dùng làm cơ quan yêu cầu. Khi gửi biểu mẫu (biểu mẫu đăng ký), một hàm xử lý được gọi để bắt đầu cuộc gọi tìm nạp /api/user/register. Tôi đã sử dụng event.preventDefault()dòng đầu tiên của hàm xử lý này, tất cả các dòng khác, như tạo phần thân yêu cầu cũng như lệnh gọi tìm nạp được viết sau event.preventDefault(). Điều này trả lại a pending promise.

Nhưng khi tôi đặt mã hình thành phần thân yêu cầu phía trên event.preventDefault(), nó trả về lời hứa thực sự. Như thế này:

event.preventDefault();
    const data = {
        'email': email,
        'password': password
    }
    fetch(...)
     ...

thay vì :

     const data = {
            'email': email,
            'password': password
        }
     event.preventDefault();
     fetch(...)
     ...
0 hữu ích 0 bình luận chia sẻ
loading
Không tìm thấy câu trả lời bạn tìm kiếm? Duyệt qua các câu hỏi được gắn thẻ javascript node.js promise , hoặc hỏi câu hỏi của bạn.

Có thể bạn quan tâm

loading